Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

XUL persist disabled in FF 3.0.5

21 views
Skip to first unread message

Bryan White

unread,
Dec 19, 2008, 11:17:42 AM12/19/08
to
I have a bunch of applications that run as web pages inside FireFox as
signed Jar files with XUL and JavaScript. These are all internal
company applications.

These applications depend on persist attributes to maintain layout state
and various other pieces if data. This includes thinks like the width
of columns in a tree control.

It seems that with FF 3.0.5, this capability has been disabled. This is
about all the detail I can find about it:
http://www.mozilla.org/security/announce/2008/mfsa2008-63.html

The bug id is blocked from public view.

From the description it seems that the change is explicitly to prevent
the kind of things I want to do with 'persist'.

Is there any work around, or do I have to force my users to jump back to
the prior version?

Note: my apps do make use of enablePrivilege("UniversalXPConnect"). I
am guessing that any sort of workaround would involve elevated
permissions of some sort.

Bryan

Neil

unread,
Dec 19, 2008, 1:07:45 PM12/19/08
to
Bryan White wrote:

> Is there any work around, or do I have to force my users to jump back
> to the prior version?
>
> Note: my apps do make use of enablePrivilege("UniversalXPConnect"). I
> am guessing that any sort of workaround would involve elevated
> permissions of some sort.

You are right; the workaround is to use document.persist() instead (this
still works after enablePrivilege("UniversalBrowserWrite") or better).

--
Warning: May contain traces of nuts.

Bryan White

unread,
Dec 19, 2008, 2:51:16 PM12/19/08
to

I have been looking for but have not found much documentation on
document.persist(). I did find, what I believe is the source code in
nxXULDocument.cpp. It looks like it takes an element id and an
attribute name as parameters.

If I understand this right I need to write a function that enumerates
all elements that have an 'id' and a 'persist' attribute, parse the
'persist' attribute list and call document.persist() for each
id/attribute pair. I am guessing this should be done early in the
'onload' event handler for the document. It looks like that will
restore the attribute and add it to the persisted set for the document.

Is this about right or have I mis-interpreted something?

Bryan

Neil

unread,
Dec 20, 2008, 1:02:52 PM12/20/08
to
Bryan White wrote:

> If I understand this right I need to write a function that enumerates
> all elements that have an 'id' and a 'persist' attribute, parse the
> 'persist' attribute list and call document.persist() for each
> id/attribute pair. I am guessing this should be done early in the
> 'onload' event handler for the document. It looks like that will
> restore the attribute and add it to the persisted set for the document.

Hmm, things look worse than I first thought; although you can request
privileges to successfully call document.persist() the persisted
attributes never get restored :-(

Bryan White

unread,
Dec 22, 2008, 7:57:03 AM12/22/08
to
Neil wrote:
> Hmm, things look worse than I first thought; although you can request
> privileges to successfully call document.persist() the persisted
> attributes never get restored :-(

Is this likely to be rectified in the near term?

I am evaluating alternatives. The two general approaches that occur to
me are storing the data client side or server side.

Functionally server side storage would work slightly different from the
user's perspective because the data would be bound to the users login
id instead of there firefox profile. This shows up when the user
accesses the site via different computers or uses different accounts on
the same computer. Both have advantages and I see reason to reject
either approach.

However server side storage would be a little slower and could get
complicated when the client side shuts down. It would end up being an
XMLHttpRequest in the 'onunload' handler. In am not certain an async
request would work here and a sync request might cause unexplained hangs
when the server is slow to respond.

On the client side, I am looking at the interfaces listed on this page:
https://developer.mozilla.org/en/Interfaces

Possibilities that jump out at me include:
mozISQL* - Seems undocumented on the MDC web site
mosIStorage* - docs say: It is available to trusted callers,
- meaning extensions and Firefox components only
- I think this means not available via EnablePrivilege
nsICookie* - what are the limits of the number and size
- of cookies I can create.
nsIFile*/nsILocalFile - My guess is these interfaces are not
- not available to my apps.
nsiPref*
nsIRegistry - may be Windows specific?

Any suggestions on what direction I should pursue would be appreciated.

Bryan

j...@snelders.net

unread,
Dec 22, 2008, 8:31:56 AM12/22/08
to
Ran into the same problem here with web based applications.

It's a shame this even blocks signed web based applications as Bryan
mentions. Hopefully Mozilla recognizes in the future that more and
more people are relying on XUL for web based applications. There
really should have been some solution, either by signing your
application or otherwise by requesting extra privileges as Neil
suggested.

Jan

Bryan White

unread,
Dec 22, 2008, 9:11:45 AM12/22/08
to
Bryan White wrote:

> the same computer. Both have advantages and I see reason to reject
> either approach.

Opps. That should read: Both have advantages and I see NO reason to
reject either approach.

Bryan

Neil

unread,
Jan 4, 2009, 10:34:08 AM1/4/09
to
Bryan White wrote:

> Neil wrote:
>
>> Hmm, things look worse than I first thought; although you can request
>> privileges to successfully call document.persist() the persisted
>> attributes never get restored :-(
>
> Is this likely to be rectified in the near term?

Well, we've just had the Christmas/New Year break, which might explain
why nothing's happened in the last two weeks.

If you're interested in progressing the document.persist issue, then a
good move would be to write a test case that uses enhanced security to
show that document.persist can still save the attributes to the profile
but that they do not get restored. Attach that test to a new bug, and
request blocking-3.0.6 on the bug.

lfournie

unread,
Jan 7, 2009, 8:57:04 AM1/7/09
to
On Jan 4, 4:34 pm, Neil <n...@parkwaycc.co.uk> wrote:

> If you're interested in progressing the document.persist issue, then a
> good move would be to write a test case that uses enhanced security to
> show that document.persist can still save the attributes to the profile
> but that they do not get restored. Attach that test to a new bug, and
> request blocking-3.0.6 on the bug.

Hello all.
I have the same concern than Brian; Industry Intranet XUL application
with privilege to read local data and I use extensively the persist
attribute to store user's choice.

I tried on October 22th 2008 to warm Mozilla developers on this
(https://bugzilla.mozilla.org/show_bug.cgi?id=461114) bug it seems
nobody is taking care of this !

As Neil suggested here a simple XUL code for testing persist
attribute;

<window title="Persist Test" xmlns="http://www.mozilla.org/keymaster/
gatekeeper/there.is.only.xul">
<script type="text/javascript">
<![CDATA[
window.onload = init;
function init() {
try { netscape.security.PrivilegeManager.enablePrivilege
('UniversalXPConnect'); }
catch (e) { alert ('Set privilege !'); }
}
]]>
</script>
<vbox id="ZBOX" height="50" persist="height"></vbox><splitter/><vbox
flex="1"></vbox>
</window>

but this code does not add the 'height' attribute for ZBOX in my
localstore.rdf

So before finding a way to restore the data, could you help me
defining a good test example where persist data is well stored.

Thanks,

Laurent Fournier

lfournie

unread,
Jan 7, 2009, 9:00:20 AM1/7/09
to
On Jan 4, 4:34 pm, Neil <n...@parkwaycc.co.uk> wrote:

> If you're interested in progressing the document.persist issue, then a
> good move would be to write a test case that uses enhanced security to
> show that document.persist can still save the attributes to the profile
> but that they do not get restored. Attach that test to a new bug, and
> request blocking-3.0.6 on the bug.

Hello all.

Neil

unread,
Jan 8, 2009, 5:02:28 AM1/8/09
to
lfournie wrote:

><window title="Persist Test" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
><script type="text/javascript">
><![CDATA[
>window.onload = init;
>function init() {

> try { netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); }


> catch (e) { alert ('Set privilege !'); }
>}
>]]>
></script>
><vbox id="ZBOX" height="50" persist="height"></vbox><splitter/><vbox
>flex="1"></vbox>
></window>
>
>but this code does not add the 'height' attribute for ZBOX in my localstore.rdf
>
>So before finding a way to restore the data, could you help me defining a good test example where persist data is well stored.
>
>

Instead of the persist attribute you need to write
document.persist("ZBOX", "height"); in your try block i.e.

function init() {
try {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
document.persist("ZBOX", "height");


}
catch (e) { alert ('Set privilege !'); }
}

lfournie

unread,
Jan 8, 2009, 10:28:14 AM1/8/09
to
On Jan 8, 11:02 am, Neil <n...@parkwaycc.co.uk> wrote:
>                 document.persist("ZBOX", "height");

Thanks Neil,
Unfortunately, event after explicit document.persist call, my
localstore.rdf does not include the data to make persistent !
Maybe I missed something!
Did someone progress on this issue ?
Can you or someone more expert than me post a bug on persist data ASAP
for blocking 3.06 release.

Thanks

Laurent

Neil

unread,
Jan 8, 2009, 12:20:56 PM1/8/09
to
lfournie wrote:

>Unfortunately, event after explicit document.persist call, my localstore.rdf does not include the data to make persistent !
>

It seems that I misunderstood the code. It checks the privileges of the
document, not the script, so enablePrivilege isn't a workaround in this
case. Sorry about that.

Additionally, the code checks for UniversalBrowserWrite, not
UniversalXPConnect, although I don't know whether that's relevant.

Chris S

unread,
Jan 9, 2009, 6:22:16 AM1/9/09
to

I faced a similar dilemna when I tried to persist attributes of a tree
defined within an xbl binding. What I came up with was to use the
preferences to store the store the column states which has worked
well. I think it's best to stick with a local store, just for speed
and simplicity.

I tried to pull together generic version of the code I use, but I
haven't tested it. You'll need to replace "extensions.mpm" in
getBranch with your own extension name. Put a call to saveColumns
( treeElement ) in your unload and loadColumns ( treeElement ) in
load:


function Nz(obj, def) {
if (typeof(obj) == 'undefined') {
return (typeof(def) == 'undefined') ? null : def
}
return obj
}

var prefService = Components.classes["@mozilla.org/preferences-service;
1"]
.getService(Components.interfaces.nsIPrefService);

var branch = prefService.getBranch("extensions.mpm.");

var prefs = {
branch : branch,
service : prefService,
get : function(strPref, def) {
switch (branch.getPrefType(strPref)) {
case branch.PREF_STRING :
return branch.getCharPref(strPref);
case branch.PREF_INT :
return branch.getIntPref(strPref);
case branch.PREF_BOOL :
return branch.getBoolPref(strPref);
default :
def = Nz(def)
prefs.set(strPref, def);
return def;
}
},
set : function(strPref, val) {
switch (branch.getPrefType(strPref)) {
case branch.PREF_STRING :
branch.setCharPref(strPref, val);
break;
case branch.PREF_INT :
branch.setIntPref(strPref, val);
break;
case branch.PREF_BOOL :
branch.setBoolPref(strPref, val);
break;
default :
if (Nz(val)) {
switch (typeof(val)) {
case 'string' :
branch.setCharPref(strPref, val);
break;
case 'number' :
branch.setIntPref(strPref, val);
break;
case 'boolean' :
branch.setBoolPref(strPref, val);
break;
default :
branch.setCharPref(strPref, val.toSource
());
break;
}
}
}
}
}

function saveColumns(tree) {
var col= tree.columns.getFirstColumn()
var colprops = ""
var i = 1
while (col) {
if (colprops > "") colprops += ";"
colprops += [col.id, (col.width==0), col.width, i++].join(":")
col = col.getNext()
}
prefs.set("browser_columns_" + tree.id, colprops)
}

function setCol(val, index, arr) {
props = val.split(":")
if (props[0] > "") {
var c = document.getElementById(props[0])
c.hidden = (props[1]=="true")
c.setAttribute("width", props[2])
c.setAttribute("ordinal", props[3])
}
}

function loadColumns(tree) {
var bcols = tree.childNodes[0].childNodes
var colprops = prefs.get("browser_columns_" + tree.id, "")
if (colprops > "") {
var cols = colprops.split(";")
cols.forEach(setCol, cols)
}
}

lfournie

unread,
Jan 12, 2009, 6:28:37 AM1/12/09
to
Thank you Chris for your proposal to use preferences.

I wonder why the pref feature has not been also locked like the
persist feature since they both allows the same kind of security
vulnerability !

I would prefer to have some kind higher privilege with a warning alert
for end user.
It would be surprising that all the mechanics for set and get persist
attribute been removed from the FF code ! It seems that the
localstore.rdf is still used for storing windows attributes (size,
positions) for the window manager.

Is there someone who has look into the FF source code to propose a
solution to use "persist" attributes. I hope we will not be forced to
ask for a FF patch or an extension just to have this feature. Note
that in our industry, it is not infeasible that we distributes patched
tools when we really need it.

Up to now I did not have the need to CVS co the FF source code, but I
guess I will.

Laurent

lfournie

unread,
Jan 13, 2009, 4:38:03 AM1/13/09
to
Hello,

I had a look into the source code;
the file mozilla\content\xul\document\src\nsXULDocument.cpp has been
added those lines and a function:

// For non-chrome documents, persistance is simply broken
if (!IsCapabilityEnabled("UniversalBrowserRead"))
return NS_ERROR_NOT_AVAILABLE;
...
// For non-chrome documents, persistance is simply broken
if (!IsCapabilityEnabled("UniversalBrowserWrite"))
return NS_ERROR_NOT_AVAILABLE;

The added function is:
PRBool
nsXULDocument::IsCapabilityEnabled(const char* aCapabilityLabel)
{
nsresult rv;
// NodePrincipal is guarantied to be non-null
PRBool enabled = PR_FALSE;
rv = NodePrincipal()->IsCapabilityEnabled(aCapabilityLabel,
nsnull, &enabled);
if (NS_FAILED(rv))
return PR_FALSE;
return enabled;
}

I don't understand why setting those two privileges in Javascript does
not just solve the issue.
What make non chrome application the IsCapabilityEnabled function
return false ?

netscape.security.PrivilegeManager.enablePrivilege
("UniversalPreferencesRead UniversalBrowserWrite");

Any idea ?

Laurent

Neil

unread,
Jan 13, 2009, 6:51:43 AM1/13/09
to
lfournie wrote:

>I don't understand why setting those two privileges in Javascript does not just solve the issue.
>
>

Because enablePrivilege enables it for the script, not for the document
:-( [That was the mistake I made earlier.]

lfournie

unread,
Jan 13, 2009, 10:11:28 AM1/13/09
to
Hello again !

I switched all my remote apps using 'persist' attribute to prefs as
Chris. suggested before. It just increases the javascript code but
works well for me. (you can simplify Chris. code by using only string
values). There is also an advantage I did not suspect, that is you can
cross apps data value; Some user settings saved in one app can be
reload in other apps.

I simply hope that Mozilla smart developers won't find a day that
prefs is also a security vulnerability !

By the way, if someone has a trick to use 'persist' attributes, we are
still curious.

Laurent

Neil

unread,
Jan 13, 2009, 11:53:23 AM1/13/09
to
lfournie wrote:

>What make non chrome application the IsCapabilityEnabled function return false ?
>
>

This function is used so that only content chrome documents pass the
check; if for some strange reason you had a document in a theme or a
langpack then it wouldn't be able to persist attributes either.

Bryan White

unread,
Jan 27, 2009, 6:06:07 AM1/27/09
to lfournie
lfournie wrote:
> Hello again !
>
> I switched all my remote apps using 'persist' attribute to prefs as
> Chris. suggested before. It just increases the javascript code but
> works well for me. (you can simplify Chris. code by using only string
> values). There is also an advantage I did not suspect, that is you can
> cross apps data value; Some user settings saved in one app can be
> reload in other apps.
>
> I simply hope that Mozilla smart developers won't find a day that
> prefs is also a security vulnerability !

I went the other direction. I changed my code to fetch persist data
from the server in the onload event and then save it in onunload. I
globally changed all 'persist' attributes to be another attribute name
so that if persist starts working again it wont confuse the issue. The
persist data is serialized to a string by walking the DOM tree at
onunload and the reverse happens in onload.

Bryan

lfournie

unread,
Jan 28, 2009, 3:46:23 AM1/28/09
to
On Jan 27, 12:06 pm, Bryan White <bryan-n...@arcamax.com> wrote:
> I went the other direction.  I changed my code to fetch persist data
> from the server in the onload event and then save it in onunload.  I
> globally changed all 'persist' attributes to be another attribute name
> so that if persist starts working again it wont confuse the issue.  The
> persist data is serialized to a string by walking the DOM tree at
> onunload and the reverse happens in onload.
>
> Bryan

Hello Bryan,

This is also a good generic solution and as administrator of your
application, you can know exactly who are the users (authentication)
and what are their data. What solution did you chose to store
serialized string on the server ? If I had to do it, I would use a
Berkeley Database (persist hash table), far more efficient than a
RDBMS. I also use Python with mod_py Apache on server side.
Why not sharing your 'save' and 'load' function somewhere? I think a
lot of people didn't realize that the persist attribute was not
working...or are we so few people doing such remote XUL apps !

Laurent

0 new messages