Specifically, it seems like when you hover over A, and B is now shown above
A (and directly below your mouse), because of an `A:hover > B
{display:block}` type style rule, immediately the rendering engine loses
knowledge that A is actually hovered, since the mouse is now directly over B
(which is of course over A).
Consequently, I believe the `A:hover` rule goes inactive, which re-hides B a
split-millisecond later, producing a flickering effect as you move the mouse
around over A (B constantly being shown and hidden again). Again, the same
CSS/markup in content-js land produces a stable (non-flickering) effect of B
staying visible over A, when B was made visible by first hovering on A.
I've posted this screencast capture to illustrate the behavioral difference:
So, I've been trying to determine what's different about the two
environments that could be causing this divergence of behavior. Here's what
I've got so far:
1. the "panel" is an XUL popup. However, inside that XUL window, I create an
<iframe> that fills the whole panel, and it's inside that <iframe> that I am
doing all my rendering.
2. The <iframe> that is created inside the XUL document is created via
`document.createElementNS("http://www.w3.org/1999/xhtml", "iframe")`.
Moreover, both the prototype's document in content-js land, and the document
that is loaded into the iframe, are created with `<html
xmlns="http://www.w3.org/1999/xhtml">`. As far as I'm aware, this should
allow the <iframe> to be a completely separate "sandbox" inside the XUL, and
otherwise function just like a normal page.
3. The content-js prototype has <!DOCTYPE html> declared in its document, as
does the document that is loaded into the <iframe>, so both should be
activating "standards mode" rendering.
I'm working on the HTML Inspector devtool, and running into an issue with
how my CSS is rendering/behaving incorrectly. I have a standalone prototype
of the tool in content-js land, and it works fine, but when I take the same
markup and CSS and put it inside the devtool panel, what starts misbehaving
is how the nested :hover elements work when stacked on top of each other.
Specifically, it seems like when you hover over A, and B is now shown above
A (and directly below your mouse), because of an `A:hover > B
{display:block}` type style rule, immediately the rendering engine loses
knowledge that A is actually hovered, since the mouse is now directly over B
(which is of course over A).
Consequently, I believe the `A:hover` rule goes inactive, which re-hides B a
split-millisecond later, producing a flickering effect as you move the mouse
around over A (B constantly being shown and hidden again). Again, the same
CSS/markup in content-js land produces a stable (non-flickering) effect of B
staying visible over A, when B was made visible by first hovering on A.
I've posted this screencast capture to illustrate the behavioral difference:
So, I've been trying to determine what's different about the two
environments that could be causing this divergence of behavior. Here's what
I've got so far:
1. the "panel" is an XUL popup. However, inside that XUL window, I create an
<iframe> that fills the whole panel, and it's inside that <iframe> that I am
doing all my rendering.
2. The <iframe> that is created inside the XUL document is created via
`document.createElementNS("http://www.w3.org/1999/xhtml", "iframe")`.
Moreover, both the prototype's document in content-js land, and the document
that is loaded into the iframe, are created with `<html
xmlns="http://www.w3.org/1999/xhtml">`. As far as I'm aware, this should
allow the <iframe> to be a completely separate "sandbox" inside the XUL, and
otherwise function just like a normal page.
3. The content-js prototype has <!DOCTYPE html> declared in its document, as
does the document that is loaded into the <iframe>, so both should be
activating "standards mode" rendering.
4. I *do* have (in both pieces of code) JavaScript mousemove/mouseover
handlers running, which are inspecting properties for coordinate
calculations, such as the offsetLeft/offsetHeight, etc. I've heard that some
code like that can cause CSS to do "reflow" or "repaint", so I'm not sure if
that's related or not. But again, I have the same code running in both, so
not sure the difference.
Any ideas on why the behavioral difference is present? More specifically, on
what I can do to troubleshoot/fix this issue?
--Kyle
I have no idea if this is related but I recently learned that iframe
attribute "type", which determines whether the iframe is Web-like or
chrome-like, must be set on the element *before* it is inserted in the
DOM. Otherwise its value will not be obeyed.
jjb
5. Upon experimentation, whatever behavioral difference is being triggered
between these two environments, it does seem to be something related to if
an element is "invisible" (in that it is strictly displayed but has a
transparent background color and no content rendered in it).
To be more specific about the markup structure driving the screencast demo
you saw:
To use the labeling from my prior description, I have an "A" element (it's
actually a block-element styled <b>) that is positioned over an entire
attribute-list in the markup view of the inspector. It is "hidden" in that
is has nothing visible, but it is still displayed, so a :hover rule can be
targeted against it.
When you hover over this "A" element, several "B" elements (actually, they
are block-element styled <em>'s) are displayed ("B" elements all appear over
the "A" element, but are not overlapping with each other). Each "B" element
is "invisible" (nothing visible rendered, but still present), but each "B"
is sized and positioned to cover only one attribute (& value, if there is
one) in the list. So, for instance, there's one "B" element over the top of
`id="foo"` and another over `rel="bar"`.
You can see from the screencast that it appears that when you hover over a
"B" element, the whole "A" element (which is the parent container for all
the "B" elements) gets hidden, as if the A:hover rule no longer applied,
creating the flicker effect where "A" and "B" are flickering on and off as
you move your mouse over the area that would be a "B" (and "A").
But the same setup (markup/CSS) with "invisible" hover elements in
content-js doesn't suffer this problem -- "A" and "B" both stay stable and
visible while moving around over "B".
--Kyle
6. Actually, upon even further experimentation, I don't think it's related
to the element being "invisible" per se.
Again, to go back to my labeling pattern from the earlier messages, the
problem that is being exposed only in the chrome-land rendering and not in
the content-land rendering, seems to be related to an element "C" that is
being shown.
As I said before, hovering over "A" makes several "B" elements show up (that
are "invisible"). In addition, however, inside of each "B" is a
`display:none`d "C" element (technically, a block-element styled <i>).
Hovering over a "B" element shows its "C" element (`A > B:hover > C
{display:block}`).
It's important to note that the "C" element has visible content in it (in
this case, a background image), and also that the "C" element, while nested
inside the "B", does not actually cover up all the area of the "B" element.
The "C" element is relatively offset to the right and slightly down, such
that you can hover over parts of "B" without hovering over "C".
Even though you can move from "A" onto "B" without hovering over "C",
apparently the mere fact that `B:hover > C {display:block}` firing causes a
reflow/repaint is enough to confuse the engine into losing track of the fact
that both "A" and "B" are still hovered, and it hides "A" (and thus "B" and
"C" as child and grandchild elements, respectively), causing the flickering.
However, if I tell the CSS basically never to show the "C" element upon
`B:hover`, all of a sudden moving over "A" and "B" elements is *a LOT* more
stable (almost no flickering). So this behavioral difference definitely
seems to be related to the reflow/repaint on showing "C" when B is hovered.
Again, any thoughts on the difference between my content-land prototype and
my chrome-land devtool?
--Kyle
Good to understand what that `type` property is. The code is doing
`setAttribute('type', 'content')`, so I assume it's doing what you suggest,
which is to tell the iframe to behave like a content-land iframe window,
right?
--Kyle
A reliable test to determine if your iframe is type content is to
attempt to open a file using say nsILocalFile. You should get permission
denied to get property XPCComponents.classes.
jjb
>
>
> --Kyle
Note that the type attribute on a frame doesn't affect the permissions of
the code, that comes from the URL of the document. The type attribute
affects the type of the docshell. As far as any JS running inside a content
docshell is concerned it cannot see above the docshell (window.top ==
window). When JS in a chrome docshell attempts to access JS in a content
docshell it does so through the various wrappers.
While I don't know what a docshell is, I can tell you by experience that
loading an http url into an iframe with type "chrome" at element
insertion time will be able to write on your harddrive, but an iframe
with type "content" will not. I also know that a chrome url in a web
page does not have permissions of a chrome url in a xul browser type chrome.
The documentation agrees with you. So something does not add up.
jjb
> On 6/25/2011 8:38 PM, Dave Townsend wrote:
>
>> On 25 June 2011 20:20, johnjbarton<johnjbarton@**johnjbarton.com<johnj...@johnjbarton.com>>
I cannot say I have tried loading a http URL into a chrome docshell for
myself but I have loaded a chrome URL into a content docshell (the add-ons
manager f.e.) and it certainly does have full privileges.
> While I don't know what a docshell is, I can tell you by experience that
> loading an http url into an iframe with type "chrome" at element
> insertion time will be able to write on your harddrive, but an iframe
> with type "content" will not. I also know that a chrome url in a web
> page does not have permissions of a chrome url in a xul browser type
> chrome.
>
> The documentation agrees with you. So something does not add up.
You may want to test again, as you have it mixed up. Only the url loaded
determines the permissions.
This is, in general, not true.
If you have an untrusted url in a type="chrome" docshell then it can get
access to window.parent, which is a chrome JS object, and then it can
use this to subvert its normal lack of privileges, iirc.
(It may also be able to call window.close() on that chrome window,
resize it, and various other things that are normally not allowed for
content due to being in type="content" docshells and have nothing to do
with its principal.)
Loading untrusted stuff in type="chrome" docshells is NOT SAFE in general.
-Boris
Er, yes, there are a few things that are few privileges determined by
the chrome/content type as well, but the example given of access to
nsILocalFile is based on the url, not on the frame type.
What if the iframe has no URL? Then what determines the permissions?
In our specific case the outer XUL iframe had no type attribute and
URL="chrome://firebug/content/panel.html". The inner iframe had no URL.
HTML loaded into the inner iframe was not secure. Adding
type="content-primary" to the outer XUL iframe changed the tests results
so the inner iframe no longer appeared to have permissions. The
specific error message in the secure case was
Error: Permission denied for <moz-safe-about:blank> to get property
XPCComponents.classes
Source File: about:blank
Line: 1
jjb
> On 6/26/2011 2:01 AM, Neil Deakin wrote:
>
>> On 11-06-25 11:48 PM, johnjbarton wrote:
>>
>> While I don't know what a docshell is, I can tell you by experience that
>>> loading an http url into an iframe with type "chrome" at element
>>> insertion time will be able to write on your harddrive, but an iframe
>>> with type "content" will not. I also know that a chrome url in a web
>>> page does not have permissions of a chrome url in a xul browser type
>>> chrome.
>>>
>>> The documentation agrees with you. So something does not add up.
>>>
>>
>> You may want to test again, as you have it mixed up. Only the url loaded
>> determines the permissions.
>>
>
> What if the iframe has no URL? Then what determines the permissions?
>
How can it have no URL? Presumably it has at least about:blank? How do you
get content into the iframe?
In our specific case the outer XUL iframe had no type attribute and
> URL="chrome://firebug/content/panel.html". The inner iframe had no URL. HTML
> loaded into the inner iframe was not secure. Adding type="content-primary"
> to the outer XUL iframe changed the tests results so the inner iframe no
> longer appeared to have permissions. The specific error message in the
> secure case was
When a frame has no type attribute its docshell is just the same type as the
outer docshell I believe.
To be precise I should have said "What if we don't set src attribute on
the iframe?".
> How do you
> get content into the iframe?
this.htmlPreview.contentWindow.document.body.innerHTML = text;
>
> In our specific case the outer XUL iframe had no type attribute and
>> URL="chrome://firebug/content/panel.html". The inner iframe had no URL. HTML
>> loaded into the inner iframe was not secure. Adding type="content-primary"
>> to the outer XUL iframe changed the tests results so the inner iframe no
>> longer appeared to have permissions. The specific error message in the
>> secure case was
>
>
> When a frame has no type attribute its docshell is just the same type as the
> outer docshell I believe.
Based on my experience I would say " When an iframe nas no |type|
attribute it acts like it inherits the |type| attribute of it's
enclosing iframe or browser element". I think this agrees with your version.
jjb
Then they are inherited from the parent document.
The one exception is that a type="content" iframe in this situation will
never inherit a system principal from its parent document (no matter
whether that document is in a type="content" or type="chrome" docshell).
Instead it will use either a nonce principal or the codebase principal
for "about:blank". I can't recall which, but for our purpses here
they're close to equivalent.
> In our specific case the outer XUL iframe had no type attribute and
> URL="chrome://firebug/content/panel.html". The inner iframe had no URL.
> HTML loaded into the inner iframe was not secure.
Yes, the inner iframe got the permissions of
"chrome://firebug/content/panel.html" in this case.
-Boris
Can anyone point me to any reason why the rendering/interaction behavior of
such CSS would be different, given the scenario I've described?
--Kyle
Your scenario is inside a panel, right? I would assume there could be
mouse event weirdness inside a panel....
Past that, hard to say anything without a testcase.
-Boris
>When JS in a chrome docshell attempts to access JS in a content docshell it does so through the various wrappers.
>
>
That was true in Firefox 3.6 but in Firefox 4 you no longer get wrappers
when accessing system privileged content documents or system privileged
properties of content objects.
--
Warning: May contain traces of nuts.
> Based on my experience I would say " When an iframe nas no |type|
> attribute it acts like it inherits the |type| attribute of it's
> enclosing iframe or browser element".
More precisely:
The documented loaded into a chrome window is always of chrome type.
Subdocuments of chrome documents are of chrome type unless the container
element (one of iframe, browser or editor) has one of the special type
attribute values (the common ones are content, content-targetable and
content-primary) indicating that the subdocument is of content type.
This boundary has a number of special effects such has making window.top
== window and preventing documents from inheriting the principal of the
parent document. The type attribute on all frames in content documents
is ignored; subdocuments of content documents are always content documents.
mouse event weirdness that would affect the CSS rendering engine's behavior
around :hover? Or mouse event weirdness in JS? Or both?
> Past that, hard to say anything without a testcase.
http://test.getify.com/test-nested-css-hover-2.html
That works fine from content-land as a web page. But the same markup and CSS
inside an <iframe> in a panel (devtool), and the flickering occurs. A patch
to illustrate:
http://test.getify.com/mozilla/patch-for-css-hovers-bug.txt
This is a patch against the "devtools" branch btw, not sure if that matters
or not.
--Kyle
Possibly both...
> That works fine from content-land as a web page. But the same markup and
> CSS inside an <iframe> in a panel (devtool), and the flickering occurs.
Can you try to isolate some of those issues? Does it flicker without
the panel? If so, does it flicker without the iframe, just in chrome?
-Boris
I just captured:
That's a screencast trying to capture/illustrate the weird behavior. You can
see some flickering, but honestly the video capturing misses a lot of the
flickering (it's much more pronounced than is obvious in this video). In any
case, you can see what I'm talking about pretty evidently.
One thing I noticed when doing the video is that it seems to have a problem
when the mouse comes from the bottom up, but from the top down it seems to
have no flickering. Also, you can probably see that the "text" cursor seems
to appear while the flickering is occurring, like there is some hidden text
overlaid that is causing the problem or something like that.
So, on that assumption that text might be involved, I decided to remove the
"lane label" text, and try again:
Again, it's a shame this video doesn't do the flickering justice, because
the flickering is quite evident in real life. I got flickering from all
sides (incl both top and bottom) in fact, not just from the bottom... in
fact, the flickering for the top movement (totally not evident in the video)
was really, really evident in real-time observation.
In any case, I think I ruled out the text elements as being the culprit...
There's just something quite weird about :hover'ing behavior in this
panel... even factoring out the nested :hover part (the green color), in
this last testvideo I saw flickering when just moving the mouse from the
right hand side, where only the `A:hover > B {background-color:blue}` rule
would have been active, and I still got that flickering.
--------------
Is this a bug, or is it still possible that I'm doing something wrong about
instantiating the <iframe> in the proper way? I still don't understand why
the rendering engine (and mouse events related to :hover) would be different
inside a content <iframe> simply because it's hosted in a panel, but I'm
sure there's something going on I'm unaware of.
--Kyle
You might read the bottom of
https://wiki.mozilla.org/XUL:Panel_Improvements
where it says:
A number of platform-specific focus related problems exist with panels.
Child frames (<iframe> elements for example) should be avoided in
panels, mainly due to the mouse not functioning in them on Windows. In
addition, noautohide panels have significant problems on Linux.
jjb
Neil also confirmed that as jjb's URL points out issues with "focus" in
child <iframe>'s, that most of those have been addressed already (the
document is out of date), and that they wouldn't be the cause in my bug
anyway.
--Kyle