mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 559505 - Deprecate localstore.rdf and replace it with xulstore. r=enn, sr=bsmedberg
This commit is contained in:
parent
89146cacef
commit
1f842452fc
@ -296,6 +296,7 @@
|
|||||||
@BINPATH@/components/toolkit_finalizationwitness.xpt
|
@BINPATH@/components/toolkit_finalizationwitness.xpt
|
||||||
@BINPATH@/components/toolkit_formautofill.xpt
|
@BINPATH@/components/toolkit_formautofill.xpt
|
||||||
@BINPATH@/components/toolkit_osfile.xpt
|
@BINPATH@/components/toolkit_osfile.xpt
|
||||||
|
@BINPATH@/components/toolkit_xulstore.xpt
|
||||||
@BINPATH@/components/toolkitprofile.xpt
|
@BINPATH@/components/toolkitprofile.xpt
|
||||||
#ifdef MOZ_ENABLE_XREMOTE
|
#ifdef MOZ_ENABLE_XREMOTE
|
||||||
@BINPATH@/components/toolkitremote.xpt
|
@BINPATH@/components/toolkitremote.xpt
|
||||||
@ -540,6 +541,8 @@
|
|||||||
#endif
|
#endif
|
||||||
@BINPATH@/components/TelemetryStartup.js
|
@BINPATH@/components/TelemetryStartup.js
|
||||||
@BINPATH@/components/TelemetryStartup.manifest
|
@BINPATH@/components/TelemetryStartup.manifest
|
||||||
|
@BINPATH@/components/XULStore.js
|
||||||
|
@BINPATH@/components/XULStore.manifest
|
||||||
@BINPATH@/components/Webapps.js
|
@BINPATH@/components/Webapps.js
|
||||||
@BINPATH@/components/Webapps.manifest
|
@BINPATH@/components/Webapps.manifest
|
||||||
@BINPATH@/components/AppsService.js
|
@BINPATH@/components/AppsService.js
|
||||||
|
@ -1320,7 +1320,7 @@ BrowserGlue.prototype = {
|
|||||||
|
|
||||||
_migrateUI: function BG__migrateUI() {
|
_migrateUI: function BG__migrateUI() {
|
||||||
const UI_VERSION = 23;
|
const UI_VERSION = 23;
|
||||||
const BROWSER_DOCURL = "chrome://browser/content/browser.xul#";
|
const BROWSER_DOCURL = "chrome://browser/content/browser.xul";
|
||||||
let currentUIVersion = 0;
|
let currentUIVersion = 0;
|
||||||
try {
|
try {
|
||||||
currentUIVersion = Services.prefs.getIntPref("browser.migration.version");
|
currentUIVersion = Services.prefs.getIntPref("browser.migration.version");
|
||||||
@ -1328,28 +1328,22 @@ BrowserGlue.prototype = {
|
|||||||
if (currentUIVersion >= UI_VERSION)
|
if (currentUIVersion >= UI_VERSION)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this._rdf = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
|
let xulStore = Cc["@mozilla.org/xul/xulstore;1"].getService(Ci.nsIXULStore);
|
||||||
this._dataSource = this._rdf.GetDataSource("rdf:local-store");
|
|
||||||
this._dirty = false;
|
|
||||||
|
|
||||||
if (currentUIVersion < 2) {
|
if (currentUIVersion < 2) {
|
||||||
// This code adds the customizable bookmarks button.
|
// This code adds the customizable bookmarks button.
|
||||||
let currentsetResource = this._rdf.GetResource("currentset");
|
let currentset = xulStore.getValue(BROWSER_DOCURL, "nav-bar", "currentset");
|
||||||
let toolbarResource = this._rdf.GetResource(BROWSER_DOCURL + "nav-bar");
|
|
||||||
let currentset = this._getPersist(toolbarResource, currentsetResource);
|
|
||||||
// Need to migrate only if toolbar is customized and the element is not found.
|
// Need to migrate only if toolbar is customized and the element is not found.
|
||||||
if (currentset &&
|
if (currentset &&
|
||||||
currentset.indexOf("bookmarks-menu-button-container") == -1) {
|
currentset.indexOf("bookmarks-menu-button-container") == -1) {
|
||||||
currentset += ",bookmarks-menu-button-container";
|
currentset += ",bookmarks-menu-button-container";
|
||||||
this._setPersist(toolbarResource, currentsetResource, currentset);
|
xulStore.setValue(BROWSER_DOCURL, "nav-bar", "currentset", currentset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentUIVersion < 3) {
|
if (currentUIVersion < 3) {
|
||||||
// This code merges the reload/stop/go button into the url bar.
|
// This code merges the reload/stop/go button into the url bar.
|
||||||
let currentsetResource = this._rdf.GetResource("currentset");
|
let currentset = xulStore.getValue(BROWSER_DOCURL, "nav-bar", "currentset");
|
||||||
let toolbarResource = this._rdf.GetResource(BROWSER_DOCURL + "nav-bar");
|
|
||||||
let currentset = this._getPersist(toolbarResource, currentsetResource);
|
|
||||||
// Need to migrate only if toolbar is customized and all 3 elements are found.
|
// Need to migrate only if toolbar is customized and all 3 elements are found.
|
||||||
if (currentset &&
|
if (currentset &&
|
||||||
currentset.indexOf("reload-button") != -1 &&
|
currentset.indexOf("reload-button") != -1 &&
|
||||||
@ -1360,15 +1354,13 @@ BrowserGlue.prototype = {
|
|||||||
.replace(/(^|,)stop-button($|,)/, "$1$2")
|
.replace(/(^|,)stop-button($|,)/, "$1$2")
|
||||||
.replace(/(^|,)urlbar-container($|,)/,
|
.replace(/(^|,)urlbar-container($|,)/,
|
||||||
"$1urlbar-container,reload-button,stop-button$2");
|
"$1urlbar-container,reload-button,stop-button$2");
|
||||||
this._setPersist(toolbarResource, currentsetResource, currentset);
|
xulStore.setValue(BROWSER_DOCURL, "nav-bar", "currentset", currentset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentUIVersion < 4) {
|
if (currentUIVersion < 4) {
|
||||||
// This code moves the home button to the immediate left of the bookmarks menu button.
|
// This code moves the home button to the immediate left of the bookmarks menu button.
|
||||||
let currentsetResource = this._rdf.GetResource("currentset");
|
let currentset = xulStore.getValue(BROWSER_DOCURL, "nav-bar", "currentset");
|
||||||
let toolbarResource = this._rdf.GetResource(BROWSER_DOCURL + "nav-bar");
|
|
||||||
let currentset = this._getPersist(toolbarResource, currentsetResource);
|
|
||||||
// Need to migrate only if toolbar is customized and the elements are found.
|
// Need to migrate only if toolbar is customized and the elements are found.
|
||||||
if (currentset &&
|
if (currentset &&
|
||||||
currentset.indexOf("home-button") != -1 &&
|
currentset.indexOf("home-button") != -1 &&
|
||||||
@ -1376,24 +1368,21 @@ BrowserGlue.prototype = {
|
|||||||
currentset = currentset.replace(/(^|,)home-button($|,)/, "$1$2")
|
currentset = currentset.replace(/(^|,)home-button($|,)/, "$1$2")
|
||||||
.replace(/(^|,)bookmarks-menu-button-container($|,)/,
|
.replace(/(^|,)bookmarks-menu-button-container($|,)/,
|
||||||
"$1home-button,bookmarks-menu-button-container$2");
|
"$1home-button,bookmarks-menu-button-container$2");
|
||||||
this._setPersist(toolbarResource, currentsetResource, currentset);
|
xulStore.setValue(BROWSER_DOCURL, "nav-bar", "currentset", currentset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentUIVersion < 5) {
|
if (currentUIVersion < 5) {
|
||||||
// This code uncollapses PersonalToolbar if its collapsed status is not
|
// This code uncollapses PersonalToolbar if its collapsed status is not
|
||||||
// persisted, and user customized it or changed default bookmarks.
|
// persisted, and user customized it or changed default bookmarks.
|
||||||
let toolbarResource = this._rdf.GetResource(BROWSER_DOCURL + "PersonalToolbar");
|
//
|
||||||
let collapsedResource = this._rdf.GetResource("collapsed");
|
|
||||||
let collapsed = this._getPersist(toolbarResource, collapsedResource);
|
|
||||||
// If the user does not have a persisted value for the toolbar's
|
// If the user does not have a persisted value for the toolbar's
|
||||||
// "collapsed" attribute, try to determine whether it's customized.
|
// "collapsed" attribute, try to determine whether it's customized.
|
||||||
if (collapsed === null) {
|
if (!xulStore.hasValue(BROWSER_DOCURL, "PersonalToolbar", "collapsed")) {
|
||||||
// We consider the toolbar customized if it has more than
|
// We consider the toolbar customized if it has more than
|
||||||
// 3 children, or if it has a persisted currentset value.
|
// 3 children, or if it has a persisted currentset value.
|
||||||
let currentsetResource = this._rdf.GetResource("currentset");
|
let toolbarIsCustomized = xulStore.hasValue(BROWSER_DOCURL,
|
||||||
let toolbarIsCustomized = !!this._getPersist(toolbarResource,
|
"PersonalToolbar", "currentset");
|
||||||
currentsetResource);
|
|
||||||
let getToolbarFolderCount = function () {
|
let getToolbarFolderCount = function () {
|
||||||
let toolbarFolder =
|
let toolbarFolder =
|
||||||
PlacesUtils.getFolderContents(PlacesUtils.toolbarFolderId).root;
|
PlacesUtils.getFolderContents(PlacesUtils.toolbarFolderId).root;
|
||||||
@ -1403,7 +1392,7 @@ BrowserGlue.prototype = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (toolbarIsCustomized || getToolbarFolderCount() > 3) {
|
if (toolbarIsCustomized || getToolbarFolderCount() > 3) {
|
||||||
this._setPersist(toolbarResource, collapsedResource, "false");
|
xulStore.setValue(BROWSER_DOCURL, "PersonalToolbar", "collapsed", "false");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1419,9 +1408,7 @@ BrowserGlue.prototype = {
|
|||||||
|
|
||||||
if (currentUIVersion < 9) {
|
if (currentUIVersion < 9) {
|
||||||
// This code adds the customizable downloads buttons.
|
// This code adds the customizable downloads buttons.
|
||||||
let currentsetResource = this._rdf.GetResource("currentset");
|
let currentset = xulStore.getValue(BROWSER_DOCURL, "nav-bar", "currentset");
|
||||||
let toolbarResource = this._rdf.GetResource(BROWSER_DOCURL + "nav-bar");
|
|
||||||
let currentset = this._getPersist(toolbarResource, currentsetResource);
|
|
||||||
|
|
||||||
// Since the Downloads button is located in the navigation bar by default,
|
// Since the Downloads button is located in the navigation bar by default,
|
||||||
// migration needs to happen only if the toolbar was customized using a
|
// migration needs to happen only if the toolbar was customized using a
|
||||||
@ -1442,7 +1429,7 @@ BrowserGlue.prototype = {
|
|||||||
currentset = currentset.replace(/(^|,)window-controls($|,)/,
|
currentset = currentset.replace(/(^|,)window-controls($|,)/,
|
||||||
"$1downloads-button,window-controls$2")
|
"$1downloads-button,window-controls$2")
|
||||||
}
|
}
|
||||||
this._setPersist(toolbarResource, currentsetResource, currentset);
|
xulStore.setValue(BROWSER_DOCURL, "nav-bar", "currentset", currentset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1472,15 +1459,13 @@ BrowserGlue.prototype = {
|
|||||||
if (currentUIVersion < 12) {
|
if (currentUIVersion < 12) {
|
||||||
// Remove bookmarks-menu-button-container, then place
|
// Remove bookmarks-menu-button-container, then place
|
||||||
// bookmarks-menu-button into its position.
|
// bookmarks-menu-button into its position.
|
||||||
let currentsetResource = this._rdf.GetResource("currentset");
|
let currentset = xulStore.getValue(BROWSER_DOCURL, "nav-bar", "currentset");
|
||||||
let toolbarResource = this._rdf.GetResource(BROWSER_DOCURL + "nav-bar");
|
|
||||||
let currentset = this._getPersist(toolbarResource, currentsetResource);
|
|
||||||
// Need to migrate only if toolbar is customized.
|
// Need to migrate only if toolbar is customized.
|
||||||
if (currentset) {
|
if (currentset) {
|
||||||
if (currentset.contains("bookmarks-menu-button-container")) {
|
if (currentset.contains("bookmarks-menu-button-container")) {
|
||||||
currentset = currentset.replace(/(^|,)bookmarks-menu-button-container($|,)/,
|
currentset = currentset.replace(/(^|,)bookmarks-menu-button-container($|,)/,
|
||||||
"$1bookmarks-menu-button$2");
|
"$1bookmarks-menu-button$2");
|
||||||
this._setPersist(toolbarResource, currentsetResource, currentset);
|
xulStore.setValue(BROWSER_DOCURL, "nav-bar", "currentset", currentset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1501,20 +1486,16 @@ BrowserGlue.prototype = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (currentUIVersion < 16) {
|
if (currentUIVersion < 16) {
|
||||||
let toolbarResource = this._rdf.GetResource(BROWSER_DOCURL + "nav-bar");
|
let isCollapsed = xulStore.getValue(BROWSER_DOCURL, "nav-bar", "collapsed");
|
||||||
let collapsedResource = this._rdf.GetResource("collapsed");
|
|
||||||
let isCollapsed = this._getPersist(toolbarResource, collapsedResource);
|
|
||||||
if (isCollapsed == "true") {
|
if (isCollapsed == "true") {
|
||||||
this._setPersist(toolbarResource, collapsedResource, "false");
|
xulStore.setValue(BROWSER_DOCURL, "nav-bar", "collapsed", "false");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert the bookmarks-menu-button into the nav-bar if it isn't already
|
// Insert the bookmarks-menu-button into the nav-bar if it isn't already
|
||||||
// there.
|
// there.
|
||||||
if (currentUIVersion < 17) {
|
if (currentUIVersion < 17) {
|
||||||
let currentsetResource = this._rdf.GetResource("currentset");
|
let currentset = xulStore.getValue(BROWSER_DOCURL, "nav-bar", "currentset");
|
||||||
let toolbarResource = this._rdf.GetResource(BROWSER_DOCURL + "nav-bar");
|
|
||||||
let currentset = this._getPersist(toolbarResource, currentsetResource);
|
|
||||||
// Need to migrate only if toolbar is customized.
|
// Need to migrate only if toolbar is customized.
|
||||||
if (currentset) {
|
if (currentset) {
|
||||||
if (!currentset.contains("bookmarks-menu-button")) {
|
if (!currentset.contains("bookmarks-menu-button")) {
|
||||||
@ -1531,7 +1512,7 @@ BrowserGlue.prototype = {
|
|||||||
currentset = currentset.replace(/(^|,)window-controls($|,)/,
|
currentset = currentset.replace(/(^|,)window-controls($|,)/,
|
||||||
"$1bookmarks-menu-button,window-controls$2")
|
"$1bookmarks-menu-button,window-controls$2")
|
||||||
}
|
}
|
||||||
this._setPersist(toolbarResource, currentsetResource, currentset);
|
xulStore.setValue(BROWSER_DOCURL, "nav-bar", "currentset", currentset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1541,12 +1522,8 @@ BrowserGlue.prototype = {
|
|||||||
let toolbars = ["navigator-toolbox", "nav-bar", "PersonalToolbar",
|
let toolbars = ["navigator-toolbox", "nav-bar", "PersonalToolbar",
|
||||||
"addon-bar", "TabsToolbar", "toolbar-menubar"];
|
"addon-bar", "TabsToolbar", "toolbar-menubar"];
|
||||||
for (let resourceName of ["mode", "iconsize"]) {
|
for (let resourceName of ["mode", "iconsize"]) {
|
||||||
let resource = this._rdf.GetResource(resourceName);
|
|
||||||
for (let toolbarId of toolbars) {
|
for (let toolbarId of toolbars) {
|
||||||
let toolbar = this._rdf.GetResource(BROWSER_DOCURL + toolbarId);
|
xulStore.removeValue(BROWSER_DOCURL, toolbarId, resourceName);
|
||||||
if (this._getPersist(toolbar, resource)) {
|
|
||||||
this._setPersist(toolbar, resource);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1569,21 +1546,13 @@ BrowserGlue.prototype = {
|
|||||||
|
|
||||||
if (currentUIVersion < 20) {
|
if (currentUIVersion < 20) {
|
||||||
// Remove persisted collapsed state from TabsToolbar.
|
// Remove persisted collapsed state from TabsToolbar.
|
||||||
let resource = this._rdf.GetResource("collapsed");
|
xulStore.removeValue(BROWSER_DOCURL, "TabsToolbar", "collapsed");
|
||||||
let toolbar = this._rdf.GetResource(BROWSER_DOCURL + "TabsToolbar");
|
|
||||||
if (this._getPersist(toolbar, resource)) {
|
|
||||||
this._setPersist(toolbar, resource);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentUIVersion < 21) {
|
if (currentUIVersion < 21) {
|
||||||
// Make sure the 'toolbarbutton-1' class will always be present from here
|
// Make sure the 'toolbarbutton-1' class will always be present from here
|
||||||
// on out.
|
// on out.
|
||||||
let button = this._rdf.GetResource(BROWSER_DOCURL + "bookmarks-menu-button");
|
xulStore.removeValue(BROWSER_DOCURL, "bookmarks-menu-button", "class");
|
||||||
let classResource = this._rdf.GetResource("class");
|
|
||||||
if (this._getPersist(button, classResource)) {
|
|
||||||
this._setPersist(button, classResource);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentUIVersion < 22) {
|
if (currentUIVersion < 22) {
|
||||||
@ -1603,49 +1572,10 @@ BrowserGlue.prototype = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._dirty)
|
|
||||||
this._dataSource.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush();
|
|
||||||
|
|
||||||
delete this._rdf;
|
|
||||||
delete this._dataSource;
|
|
||||||
|
|
||||||
// Update the migration version.
|
// Update the migration version.
|
||||||
Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
|
Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
|
||||||
},
|
},
|
||||||
|
|
||||||
_getPersist: function BG__getPersist(aSource, aProperty) {
|
|
||||||
var target = this._dataSource.GetTarget(aSource, aProperty, true);
|
|
||||||
if (target instanceof Ci.nsIRDFLiteral)
|
|
||||||
return target.Value;
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
|
|
||||||
_setPersist: function BG__setPersist(aSource, aProperty, aTarget) {
|
|
||||||
this._dirty = true;
|
|
||||||
try {
|
|
||||||
var oldTarget = this._dataSource.GetTarget(aSource, aProperty, true);
|
|
||||||
if (oldTarget) {
|
|
||||||
if (aTarget)
|
|
||||||
this._dataSource.Change(aSource, aProperty, oldTarget, this._rdf.GetLiteral(aTarget));
|
|
||||||
else
|
|
||||||
this._dataSource.Unassert(aSource, aProperty, oldTarget);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this._dataSource.Assert(aSource, aProperty, this._rdf.GetLiteral(aTarget), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the entry to the persisted set for this document if it's not there.
|
|
||||||
// This code is mostly borrowed from XULDocument::Persist.
|
|
||||||
let docURL = aSource.ValueUTF8.split("#")[0];
|
|
||||||
let docResource = this._rdf.GetResource(docURL);
|
|
||||||
let persistResource = this._rdf.GetResource("http://home.netscape.com/NC-rdf#persist");
|
|
||||||
if (!this._dataSource.HasAssertion(docResource, persistResource, aSource, true)) {
|
|
||||||
this._dataSource.Assert(docResource, persistResource, aSource, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(ex) {}
|
|
||||||
},
|
|
||||||
|
|
||||||
// ------------------------------
|
// ------------------------------
|
||||||
// public nsIBrowserGlue members
|
// public nsIBrowserGlue members
|
||||||
// ------------------------------
|
// ------------------------------
|
||||||
|
@ -1020,10 +1020,6 @@ XPCOMUtils.defineLazyServiceGetter(PlacesUIUtils, "RDF",
|
|||||||
"@mozilla.org/rdf/rdf-service;1",
|
"@mozilla.org/rdf/rdf-service;1",
|
||||||
"nsIRDFService");
|
"nsIRDFService");
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(PlacesUIUtils, "localStore", function() {
|
|
||||||
return PlacesUIUtils.RDF.GetDataSource("rdf:local-store");
|
|
||||||
});
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(PlacesUIUtils, "ellipsis", function() {
|
XPCOMUtils.defineLazyGetter(PlacesUIUtils, "ellipsis", function() {
|
||||||
return Services.prefs.getComplexValue("intl.ellipsis",
|
return Services.prefs.getComplexValue("intl.ellipsis",
|
||||||
Ci.nsIPrefLocalizedString).data;
|
Ci.nsIPrefLocalizedString).data;
|
||||||
|
@ -23,6 +23,14 @@ function PlacesTreeView(aFlatList, aOnOpenFlatContainer, aController) {
|
|||||||
PlacesTreeView.prototype = {
|
PlacesTreeView.prototype = {
|
||||||
get wrappedJSObject() this,
|
get wrappedJSObject() this,
|
||||||
|
|
||||||
|
__xulStore: null,
|
||||||
|
get _xulStore() {
|
||||||
|
if (!this.__xulStore) {
|
||||||
|
this.__xulStore = Cc["@mozilla.org/xul/xulstore;1"].getService(Ci.nsIXULStore);
|
||||||
|
}
|
||||||
|
return this.__xulStore;
|
||||||
|
},
|
||||||
|
|
||||||
__dateService: null,
|
__dateService: null,
|
||||||
get _dateService() {
|
get _dateService() {
|
||||||
if (!this.__dateService) {
|
if (!this.__dateService) {
|
||||||
@ -307,11 +315,15 @@ PlacesTreeView.prototype = {
|
|||||||
if (!this._flatList &&
|
if (!this._flatList &&
|
||||||
curChild instanceof Ci.nsINavHistoryContainerResultNode &&
|
curChild instanceof Ci.nsINavHistoryContainerResultNode &&
|
||||||
!this._controller.hasCachedLivemarkInfo(curChild)) {
|
!this._controller.hasCachedLivemarkInfo(curChild)) {
|
||||||
let resource = this._getResourceForNode(curChild);
|
let uri = curChild.uri;
|
||||||
let isopen = resource != null &&
|
let isopen = false;
|
||||||
PlacesUIUtils.localStore.HasAssertion(resource,
|
|
||||||
openLiteral,
|
if (uri) {
|
||||||
trueLiteral, true);
|
let docURI = this._getDocumentURI();
|
||||||
|
let val = this._xulStore.getValue(docURI, uri, "open");
|
||||||
|
isopen = (val == "true");
|
||||||
|
}
|
||||||
|
|
||||||
if (isopen != curChild.containerOpen)
|
if (isopen != curChild.containerOpen)
|
||||||
aToOpen.push(curChild);
|
aToOpen.push(curChild);
|
||||||
else if (curChild.containerOpen && curChild.childCount > 0)
|
else if (curChild.containerOpen && curChild.childCount > 0)
|
||||||
@ -1109,11 +1121,16 @@ PlacesTreeView.prototype = {
|
|||||||
return Ci.nsINavHistoryResultTreeViewer.INDEX_INVISIBLE;
|
return Ci.nsINavHistoryResultTreeViewer.INDEX_INVISIBLE;
|
||||||
},
|
},
|
||||||
|
|
||||||
_getResourceForNode: function PTV_getResourceForNode(aNode)
|
// Retrieves an nsIURI for the document
|
||||||
|
_documentURI: null,
|
||||||
|
_getDocumentURI: function()
|
||||||
{
|
{
|
||||||
let uri = aNode.uri;
|
if (!this._documentURI) {
|
||||||
NS_ASSERT(uri, "if there is no uri, we can't persist the open state");
|
let ioService = Cc["@mozilla.org/network/io-service;1"].
|
||||||
return uri ? PlacesUIUtils.RDF.GetResource(uri) : null;
|
getService(Ci.nsIIOService);
|
||||||
|
this._documentURI = ioService.newURI(document.URL, null, null);
|
||||||
|
}
|
||||||
|
return this._documentURI;
|
||||||
},
|
},
|
||||||
|
|
||||||
// nsITreeView
|
// nsITreeView
|
||||||
@ -1497,15 +1514,16 @@ PlacesTreeView.prototype = {
|
|||||||
|
|
||||||
// Persist containers open status, but never persist livemarks.
|
// Persist containers open status, but never persist livemarks.
|
||||||
if (!this._controller.hasCachedLivemarkInfo(node)) {
|
if (!this._controller.hasCachedLivemarkInfo(node)) {
|
||||||
let resource = this._getResourceForNode(node);
|
let uri = node.uri;
|
||||||
if (resource) {
|
|
||||||
const openLiteral = PlacesUIUtils.RDF.GetResource("http://home.netscape.com/NC-rdf#open");
|
|
||||||
const trueLiteral = PlacesUIUtils.RDF.GetLiteral("true");
|
|
||||||
|
|
||||||
if (node.containerOpen)
|
if (uri) {
|
||||||
PlacesUIUtils.localStore.Unassert(resource, openLiteral, trueLiteral);
|
let docURI = this._getDocumentURI();
|
||||||
else
|
|
||||||
PlacesUIUtils.localStore.Assert(resource, openLiteral, trueLiteral, true);
|
if (node.containerOpen) {
|
||||||
|
this._xulStore.removeValue(docURI, uri, "open");
|
||||||
|
} else {
|
||||||
|
this._xulStore.setValue(docURI, uri, "open", "true");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,62 +5,25 @@
|
|||||||
/**
|
/**
|
||||||
* Tests PersonalToolbar migration path.
|
* Tests PersonalToolbar migration path.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let bg = Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsIObserver);
|
let bg = Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsIObserver);
|
||||||
let gOriginalMigrationVersion;
|
let gOriginalMigrationVersion;
|
||||||
const BROWSER_URL = getBrowserURL();
|
const BROWSER_URL = getBrowserURL();
|
||||||
|
|
||||||
let localStore = {
|
let localStore = {
|
||||||
get RDF() Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService),
|
get xulStore() Cc["@mozilla.org/xul/xulstore;1"].getService(Ci.nsIXULStore),
|
||||||
get store() this.RDF.GetDataSource("rdf:local-store"),
|
|
||||||
|
|
||||||
get toolbar()
|
getValue: function getValue(aProperty)
|
||||||
{
|
{
|
||||||
delete this.toolbar;
|
return this.xulStore.getValue(BROWSER_URL, "PersonalToolbar", aProperty);
|
||||||
let toolbar = this.RDF.GetResource(BROWSER_URL + "#PersonalToolbar");
|
|
||||||
// Add the entry to the persisted set for this document if it's not there.
|
|
||||||
// See XULDocument::Persist.
|
|
||||||
let doc = this.RDF.GetResource(BROWSER_URL);
|
|
||||||
let persist = this.RDF.GetResource("http://home.netscape.com/NC-rdf#persist");
|
|
||||||
if (!this.store.HasAssertion(doc, persist, toolbar, true)) {
|
|
||||||
this.store.Assert(doc, persist, toolbar, true);
|
|
||||||
}
|
|
||||||
return this.toolbar = toolbar;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getPersist: function getPersist(aProperty)
|
setValue: function setValue(aProperty, aValue)
|
||||||
{
|
{
|
||||||
let property = this.RDF.GetResource(aProperty);
|
if (aValue) {
|
||||||
let target = this.store.GetTarget(this.toolbar, property, true);
|
this.xulStore.setValue(BROWSER_URL, "PersonalToolbar", aProperty, aValue);
|
||||||
if (target instanceof Ci.nsIRDFLiteral)
|
} else {
|
||||||
return target.Value;
|
this.xulStore.removeValue(BROWSER_URL, "PersonalToolbar", aProperty);
|
||||||
return null;
|
|
||||||
},
|
|
||||||
|
|
||||||
setPersist: function setPersist(aProperty, aValue)
|
|
||||||
{
|
|
||||||
let property = this.RDF.GetResource(aProperty);
|
|
||||||
let value = aValue ? this.RDF.GetLiteral(aValue) : null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
let oldTarget = this.store.GetTarget(this.toolbar, property, true);
|
|
||||||
if (oldTarget && value) {
|
|
||||||
this.store.Change(this.toolbar, property, oldTarget, value);
|
|
||||||
}
|
|
||||||
else if (value) {
|
|
||||||
this.store.Assert(this.toolbar, property, value, true);
|
|
||||||
}
|
|
||||||
else if (oldTarget) {
|
|
||||||
this.store.Unassert(this.toolbar, property, oldTarget);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch(ex) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.store.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -69,17 +32,17 @@ let gTests = [
|
|||||||
function test_explicitly_collapsed_toolbar()
|
function test_explicitly_collapsed_toolbar()
|
||||||
{
|
{
|
||||||
info("An explicitly collapsed toolbar should not be uncollapsed.");
|
info("An explicitly collapsed toolbar should not be uncollapsed.");
|
||||||
localStore.setPersist("collapsed", "true");
|
localStore.setValue("collapsed", "true");
|
||||||
bg.observe(null, "browser-glue-test", "force-ui-migration");
|
bg.observe(null, "browser-glue-test", "force-ui-migration");
|
||||||
is(localStore.getPersist("collapsed"), "true", "Toolbar is collapsed");
|
is(localStore.getValue("collapsed"), "true", "Toolbar is collapsed");
|
||||||
},
|
},
|
||||||
|
|
||||||
function test_customized_toolbar()
|
function test_customized_toolbar()
|
||||||
{
|
{
|
||||||
info("A customized toolbar should be uncollapsed.");
|
info("A customized toolbar should be uncollapsed.");
|
||||||
localStore.setPersist("currentset", "splitter");
|
localStore.setValue("currentset", "splitter");
|
||||||
bg.observe(null, "browser-glue-test", "force-ui-migration");
|
bg.observe(null, "browser-glue-test", "force-ui-migration");
|
||||||
is(localStore.getPersist("collapsed"), "false", "Toolbar has been uncollapsed");
|
is(localStore.getValue("collapsed"), "false", "Toolbar has been uncollapsed");
|
||||||
},
|
},
|
||||||
|
|
||||||
function test_many_bookmarks_toolbar()
|
function test_many_bookmarks_toolbar()
|
||||||
@ -98,8 +61,12 @@ function test_many_bookmarks_toolbar()
|
|||||||
PlacesUtils.bookmarks.insertSeparator(PlacesUtils.toolbarFolderId,
|
PlacesUtils.bookmarks.insertSeparator(PlacesUtils.toolbarFolderId,
|
||||||
PlacesUtils.bookmarks.DEFAULT_INDEX)
|
PlacesUtils.bookmarks.DEFAULT_INDEX)
|
||||||
);
|
);
|
||||||
|
ids.push(
|
||||||
|
PlacesUtils.bookmarks.insertSeparator(PlacesUtils.toolbarFolderId,
|
||||||
|
PlacesUtils.bookmarks.DEFAULT_INDEX)
|
||||||
|
);
|
||||||
bg.observe(null, "browser-glue-test", "force-ui-migration");
|
bg.observe(null, "browser-glue-test", "force-ui-migration");
|
||||||
is(localStore.getPersist("collapsed"), "false", "Toolbar has been uncollapsed");
|
is(localStore.getValue("collapsed"), "false", "Toolbar has been uncollapsed");
|
||||||
},
|
},
|
||||||
|
|
||||||
];
|
];
|
||||||
@ -109,14 +76,14 @@ function test()
|
|||||||
gOriginalMigrationVersion = Services.prefs.getIntPref("browser.migration.version");
|
gOriginalMigrationVersion = Services.prefs.getIntPref("browser.migration.version");
|
||||||
registerCleanupFunction(clean);
|
registerCleanupFunction(clean);
|
||||||
|
|
||||||
if (localStore.getPersist("currentset") !== null) {
|
if (localStore.getValue("currentset") !== null) {
|
||||||
info("Toolbar currentset was persisted by a previous test, fixing it.");
|
info("Toolbar currentset was persisted by a previous test, fixing it.");
|
||||||
localStore.setPersist("currentset", null);
|
localStore.setValue("currentset", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (localStore.getPersist("collapsed") !== null) {
|
if (localStore.getValue("collapsed") !== null) {
|
||||||
info("Toolbar collapsed status was persisted by a previous test, fixing it.");
|
info("Toolbar collapsed status was persisted by a previous test, fixing it.");
|
||||||
localStore.setPersist("collapsed", null);
|
localStore.setValue("collapsed", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (gTests.length) {
|
while (gTests.length) {
|
||||||
@ -129,7 +96,7 @@ function test()
|
|||||||
function clean()
|
function clean()
|
||||||
{
|
{
|
||||||
Services.prefs.setIntPref("browser.migration.version", gOriginalMigrationVersion);
|
Services.prefs.setIntPref("browser.migration.version", gOriginalMigrationVersion);
|
||||||
localStore.setPersist("currentset", null);
|
localStore.setValue("currentset", null);
|
||||||
localStore.setPersist("collapsed", null);
|
localStore.setValue("collapsed", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,6 +303,7 @@
|
|||||||
@BINPATH@/components/toolkit_finalizationwitness.xpt
|
@BINPATH@/components/toolkit_finalizationwitness.xpt
|
||||||
@BINPATH@/components/toolkit_formautofill.xpt
|
@BINPATH@/components/toolkit_formautofill.xpt
|
||||||
@BINPATH@/components/toolkit_osfile.xpt
|
@BINPATH@/components/toolkit_osfile.xpt
|
||||||
|
@BINPATH@/components/toolkit_xulstore.xpt
|
||||||
@BINPATH@/components/toolkitprofile.xpt
|
@BINPATH@/components/toolkitprofile.xpt
|
||||||
#ifdef MOZ_ENABLE_XREMOTE
|
#ifdef MOZ_ENABLE_XREMOTE
|
||||||
@BINPATH@/components/toolkitremote.xpt
|
@BINPATH@/components/toolkitremote.xpt
|
||||||
@ -503,6 +504,8 @@
|
|||||||
@BINPATH@/components/cryptoComponents.manifest
|
@BINPATH@/components/cryptoComponents.manifest
|
||||||
@BINPATH@/components/TelemetryStartup.js
|
@BINPATH@/components/TelemetryStartup.js
|
||||||
@BINPATH@/components/TelemetryStartup.manifest
|
@BINPATH@/components/TelemetryStartup.manifest
|
||||||
|
@BINPATH@/components/XULStore.js
|
||||||
|
@BINPATH@/components/XULStore.manifest
|
||||||
@BINPATH@/components/messageWakeupService.js
|
@BINPATH@/components/messageWakeupService.js
|
||||||
@BINPATH@/components/messageWakeupService.manifest
|
@BINPATH@/components/messageWakeupService.manifest
|
||||||
@BINPATH@/components/SettingsManager.js
|
@BINPATH@/components/SettingsManager.js
|
||||||
|
@ -33,9 +33,6 @@
|
|||||||
#include "nsViewManager.h"
|
#include "nsViewManager.h"
|
||||||
#include "nsIContentViewer.h"
|
#include "nsIContentViewer.h"
|
||||||
#include "nsIDOMXULElement.h"
|
#include "nsIDOMXULElement.h"
|
||||||
#include "nsIRDFNode.h"
|
|
||||||
#include "nsIRDFRemoteDataSource.h"
|
|
||||||
#include "nsIRDFService.h"
|
|
||||||
#include "nsIStreamListener.h"
|
#include "nsIStreamListener.h"
|
||||||
#include "nsITimer.h"
|
#include "nsITimer.h"
|
||||||
#include "nsDocShell.h"
|
#include "nsDocShell.h"
|
||||||
@ -44,11 +41,10 @@
|
|||||||
#include "nsXULContentSink.h"
|
#include "nsXULContentSink.h"
|
||||||
#include "nsXULContentUtils.h"
|
#include "nsXULContentUtils.h"
|
||||||
#include "nsIXULOverlayProvider.h"
|
#include "nsIXULOverlayProvider.h"
|
||||||
|
#include "nsIStringEnumerator.h"
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
#include "nsParserCIID.h"
|
#include "nsParserCIID.h"
|
||||||
#include "nsPIBoxObject.h"
|
#include "nsPIBoxObject.h"
|
||||||
#include "nsRDFCID.h"
|
|
||||||
#include "nsILocalStore.h"
|
|
||||||
#include "nsXPIDLString.h"
|
#include "nsXPIDLString.h"
|
||||||
#include "nsPIDOMWindow.h"
|
#include "nsPIDOMWindow.h"
|
||||||
#include "nsPIWindowRoot.h"
|
#include "nsPIWindowRoot.h"
|
||||||
@ -137,11 +133,6 @@ const uint32_t kMaxAttributeLength = 4096;
|
|||||||
|
|
||||||
int32_t XULDocument::gRefCnt = 0;
|
int32_t XULDocument::gRefCnt = 0;
|
||||||
|
|
||||||
nsIRDFService* XULDocument::gRDFService;
|
|
||||||
nsIRDFResource* XULDocument::kNC_persist;
|
|
||||||
nsIRDFResource* XULDocument::kNC_attribute;
|
|
||||||
nsIRDFResource* XULDocument::kNC_value;
|
|
||||||
|
|
||||||
PRLogModuleInfo* XULDocument::gXULLog;
|
PRLogModuleInfo* XULDocument::gXULLog;
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
@ -230,26 +221,11 @@ XULDocument::~XULDocument()
|
|||||||
PL_DHashTableDestroy(mBroadcasterMap);
|
PL_DHashTableDestroy(mBroadcasterMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mLocalStore) {
|
|
||||||
nsCOMPtr<nsIRDFRemoteDataSource> remote =
|
|
||||||
do_QueryInterface(mLocalStore);
|
|
||||||
if (remote)
|
|
||||||
remote->Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
delete mTemplateBuilderTable;
|
delete mTemplateBuilderTable;
|
||||||
|
|
||||||
Preferences::UnregisterCallback(XULDocument::DirectionChanged,
|
Preferences::UnregisterCallback(XULDocument::DirectionChanged,
|
||||||
"intl.uidirection.", this);
|
"intl.uidirection.", this);
|
||||||
|
|
||||||
if (--gRefCnt == 0) {
|
|
||||||
NS_IF_RELEASE(gRDFService);
|
|
||||||
|
|
||||||
NS_IF_RELEASE(kNC_persist);
|
|
||||||
NS_IF_RELEASE(kNC_attribute);
|
|
||||||
NS_IF_RELEASE(kNC_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mOffThreadCompileStringBuf) {
|
if (mOffThreadCompileStringBuf) {
|
||||||
js_free(mOffThreadCompileStringBuf);
|
js_free(mOffThreadCompileStringBuf);
|
||||||
}
|
}
|
||||||
@ -349,6 +325,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(XULDocument, XMLDocument)
|
|||||||
tmp->mTemplateBuilderTable = nullptr;
|
tmp->mTemplateBuilderTable = nullptr;
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCommandDispatcher)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCommandDispatcher)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStore)
|
||||||
//XXX We should probably unlink all the objects we traverse.
|
//XXX We should probably unlink all the objects we traverse.
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
|
|
||||||
@ -1331,10 +1308,7 @@ XULDocument::Persist(const nsAString& aID,
|
|||||||
nameSpaceID = kNameSpaceID_None;
|
nameSpaceID = kNameSpaceID_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = Persist(element, nameSpaceID, tag);
|
return Persist(element, nameSpaceID, tag);
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
@ -1345,102 +1319,39 @@ XULDocument::Persist(nsIContent* aElement, int32_t aNameSpaceID,
|
|||||||
if (!nsContentUtils::IsSystemPrincipal(NodePrincipal()))
|
if (!nsContentUtils::IsSystemPrincipal(NodePrincipal()))
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
|
||||||
// First make sure we _have_ a local store to stuff the persisted
|
if (!mLocalStore) {
|
||||||
// information into. (We might not have one if profile information
|
mLocalStore = do_GetService("@mozilla.org/xul/xulstore;1");
|
||||||
// hasn't been loaded yet...)
|
if (NS_WARN_IF(!mLocalStore)) {
|
||||||
if (!mLocalStore)
|
return NS_ERROR_NOT_INITIALIZED;
|
||||||
return NS_OK;
|
}
|
||||||
|
|
||||||
nsresult rv;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIRDFResource> element;
|
|
||||||
rv = nsXULContentUtils::GetElementResource(aElement, getter_AddRefs(element));
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
// No ID, so nothing to persist.
|
|
||||||
if (! element)
|
|
||||||
return NS_OK;
|
|
||||||
|
|
||||||
// Ick. Construct a property from the attribute. Punt on
|
|
||||||
// namespaces for now.
|
|
||||||
// Don't bother with unreasonable attributes. We clamp long values,
|
|
||||||
// but truncating attribute names turns it into a different attribute
|
|
||||||
// so there's no point in persisting anything at all
|
|
||||||
nsAtomCString attrstr(aAttribute);
|
|
||||||
if (attrstr.Length() > kMaxAttrNameLength) {
|
|
||||||
NS_WARNING("Can't persist, Attribute name too long");
|
|
||||||
return NS_ERROR_ILLEGAL_VALUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIRDFResource> attr;
|
nsAutoString id;
|
||||||
rv = gRDFService->GetResource(attrstr,
|
|
||||||
getter_AddRefs(attr));
|
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::id, id);
|
||||||
if (NS_FAILED(rv)) return rv;
|
nsAtomString attrstr(aAttribute);
|
||||||
|
|
||||||
// Turn the value into a literal
|
|
||||||
nsAutoString valuestr;
|
nsAutoString valuestr;
|
||||||
aElement->GetAttr(kNameSpaceID_None, aAttribute, valuestr);
|
aElement->GetAttr(kNameSpaceID_None, aAttribute, valuestr);
|
||||||
|
|
||||||
// prevent over-long attributes that choke the parser (bug 319846)
|
nsAutoCString utf8uri;
|
||||||
// (can't simply Truncate without testing, it's implemented
|
nsresult rv = mDocumentURI->GetSpec(utf8uri);
|
||||||
// using SetLength and will grow a short string)
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
if (valuestr.Length() > kMaxAttributeLength) {
|
return rv;
|
||||||
NS_WARNING("Truncating persisted attribute value");
|
}
|
||||||
valuestr.Truncate(kMaxAttributeLength);
|
NS_ConvertUTF8toUTF16 uri(utf8uri);
|
||||||
|
|
||||||
|
bool hasAttr;
|
||||||
|
rv = mLocalStore->HasValue(uri, id, attrstr, &hasAttr);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if there was an old value...
|
if (hasAttr && valuestr.IsEmpty()) {
|
||||||
nsCOMPtr<nsIRDFNode> oldvalue;
|
return mLocalStore->RemoveValue(uri, id, attrstr);
|
||||||
rv = mLocalStore->GetTarget(element, attr, true, getter_AddRefs(oldvalue));
|
} else {
|
||||||
if (NS_FAILED(rv)) return rv;
|
return mLocalStore->SetValue(uri, id, attrstr, valuestr);
|
||||||
|
|
||||||
if (oldvalue && valuestr.IsEmpty()) {
|
|
||||||
// ...there was an oldvalue, and they've removed it. XXXThis
|
|
||||||
// handling isn't quite right...
|
|
||||||
rv = mLocalStore->Unassert(element, attr, oldvalue);
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// Now either 'change' or 'assert' based on whether there was
|
|
||||||
// an old value.
|
|
||||||
nsCOMPtr<nsIRDFLiteral> newvalue;
|
|
||||||
rv = gRDFService->GetLiteral(valuestr.get(), getter_AddRefs(newvalue));
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
if (oldvalue) {
|
|
||||||
if (oldvalue != newvalue)
|
|
||||||
rv = mLocalStore->Change(element, attr, oldvalue, newvalue);
|
|
||||||
else
|
|
||||||
rv = NS_OK;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rv = mLocalStore->Assert(element, attr, newvalue, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
// Add it to the persisted set for this document (if it's not
|
|
||||||
// there already).
|
|
||||||
{
|
|
||||||
nsAutoCString docurl;
|
|
||||||
rv = mDocumentURI->GetSpec(docurl);
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIRDFResource> doc;
|
|
||||||
rv = gRDFService->GetResource(docurl, getter_AddRefs(doc));
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
bool hasAssertion;
|
|
||||||
rv = mLocalStore->HasAssertion(doc, kNC_persist, element, true, &hasAssertion);
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
if (! hasAssertion) {
|
|
||||||
rv = mLocalStore->Assert(doc, kNC_persist, element, true);
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1993,25 +1904,7 @@ XULDocument::Init()
|
|||||||
mCommandDispatcher = new nsXULCommandDispatcher(this);
|
mCommandDispatcher = new nsXULCommandDispatcher(this);
|
||||||
NS_ENSURE_TRUE(mCommandDispatcher, NS_ERROR_OUT_OF_MEMORY);
|
NS_ENSURE_TRUE(mCommandDispatcher, NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
// this _could_ fail; e.g., if we've tried to grab the local store
|
|
||||||
// before profiles have initialized. If so, no big deal; nothing
|
|
||||||
// will persist.
|
|
||||||
mLocalStore = do_GetService(NS_LOCALSTORE_CONTRACTID);
|
|
||||||
|
|
||||||
if (gRefCnt++ == 0) {
|
if (gRefCnt++ == 0) {
|
||||||
// Keep the RDF service cached in a member variable to make using
|
|
||||||
// it a bit less painful
|
|
||||||
rv = CallGetService("@mozilla.org/rdf/rdf-service;1", &gRDFService);
|
|
||||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF Service");
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "persist"),
|
|
||||||
&kNC_persist);
|
|
||||||
gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "attribute"),
|
|
||||||
&kNC_attribute);
|
|
||||||
gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "value"),
|
|
||||||
&kNC_value);
|
|
||||||
|
|
||||||
// ensure that the XUL prototype cache is instantiated successfully,
|
// ensure that the XUL prototype cache is instantiated successfully,
|
||||||
// so that we can use nsXULPrototypeCache::GetInstance() without
|
// so that we can use nsXULPrototypeCache::GetInstance() without
|
||||||
// null-checks in the rest of the class.
|
// null-checks in the rest of the class.
|
||||||
@ -2175,8 +2068,12 @@ XULDocument::ApplyPersistentAttributes()
|
|||||||
|
|
||||||
// Add all of the 'persisted' attributes into the content
|
// Add all of the 'persisted' attributes into the content
|
||||||
// model.
|
// model.
|
||||||
if (!mLocalStore)
|
if (!mLocalStore) {
|
||||||
return NS_OK;
|
mLocalStore = do_GetService("@mozilla.org/xul/xulstore;1");
|
||||||
|
if (NS_WARN_IF(!mLocalStore)) {
|
||||||
|
return NS_ERROR_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mApplyingPersistedAttrs = true;
|
mApplyingPersistedAttrs = true;
|
||||||
ApplyPersistentAttributesInternal();
|
ApplyPersistentAttributesInternal();
|
||||||
@ -2191,56 +2088,49 @@ XULDocument::ApplyPersistentAttributes()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
XULDocument::ApplyPersistentAttributesInternal()
|
XULDocument::ApplyPersistentAttributesInternal()
|
||||||
{
|
{
|
||||||
nsCOMArray<nsIContent> elements;
|
nsCOMArray<nsIContent> elements;
|
||||||
|
|
||||||
nsAutoCString docurl;
|
nsAutoCString utf8uri;
|
||||||
mDocumentURI->GetSpec(docurl);
|
nsresult rv = mDocumentURI->GetSpec(utf8uri);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
NS_ConvertUTF8toUTF16 uri(utf8uri);
|
||||||
|
|
||||||
nsCOMPtr<nsIRDFResource> doc;
|
// Get a list of element IDs for which persisted values are available
|
||||||
gRDFService->GetResource(docurl, getter_AddRefs(doc));
|
nsCOMPtr<nsIStringEnumerator> ids;
|
||||||
|
rv = mLocalStore->GetIDsEnumerator(uri, getter_AddRefs(ids));
|
||||||
nsCOMPtr<nsISimpleEnumerator> persisted;
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
mLocalStore->GetTargets(doc, kNC_persist, true, getter_AddRefs(persisted));
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
bool hasmore = false;
|
bool hasmore = false;
|
||||||
persisted->HasMoreElements(&hasmore);
|
ids->HasMore(&hasmore);
|
||||||
if (! hasmore)
|
if (!hasmore) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsISupports> isupports;
|
nsAutoString id;
|
||||||
persisted->GetNext(getter_AddRefs(isupports));
|
ids->GetNext(id);
|
||||||
|
|
||||||
nsCOMPtr<nsIRDFResource> resource = do_QueryInterface(isupports);
|
if (mRestrictPersistence && !mPersistenceIds.Contains(id)) {
|
||||||
if (! resource) {
|
|
||||||
NS_WARNING("expected element to be a resource");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *uri;
|
|
||||||
resource->GetValueConst(&uri);
|
|
||||||
if (! uri)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
nsAutoString id;
|
|
||||||
nsXULContentUtils::MakeElementID(this, nsDependentCString(uri), id);
|
|
||||||
|
|
||||||
if (id.IsEmpty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (mRestrictPersistence && !mPersistenceIds.Contains(id))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// This will clear the array if there are no elements.
|
// This will clear the array if there are no elements.
|
||||||
GetElementsForID(id, elements);
|
GetElementsForID(id, elements);
|
||||||
|
if (!elements.Count()) {
|
||||||
if (!elements.Count())
|
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ApplyPersistentAttributesToElements(resource, elements);
|
rv = ApplyPersistentAttributesToElements(id, elements);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -2248,71 +2138,53 @@ XULDocument::ApplyPersistentAttributesInternal()
|
|||||||
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
XULDocument::ApplyPersistentAttributesToElements(nsIRDFResource* aResource,
|
XULDocument::ApplyPersistentAttributesToElements(const nsAString &aID,
|
||||||
nsCOMArray<nsIContent>& aElements)
|
nsCOMArray<nsIContent>& aElements)
|
||||||
{
|
{
|
||||||
nsresult rv;
|
nsAutoCString utf8uri;
|
||||||
|
nsresult rv = mDocumentURI->GetSpec(utf8uri);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
NS_ConvertUTF8toUTF16 uri(utf8uri);
|
||||||
|
|
||||||
nsCOMPtr<nsISimpleEnumerator> attrs;
|
// Get a list of attributes for which persisted values are available
|
||||||
rv = mLocalStore->ArcLabelsOut(aResource, getter_AddRefs(attrs));
|
nsCOMPtr<nsIStringEnumerator> attrs;
|
||||||
if (NS_FAILED(rv)) return rv;
|
rv = mLocalStore->GetAttributeEnumerator(uri, aID, getter_AddRefs(attrs));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
bool hasmore;
|
bool hasmore = PR_FALSE;
|
||||||
rv = attrs->HasMoreElements(&hasmore);
|
attrs->HasMore(&hasmore);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (!hasmore) {
|
||||||
|
|
||||||
if (! hasmore)
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
nsCOMPtr<nsISupports> isupports;
|
|
||||||
rv = attrs->GetNext(getter_AddRefs(isupports));
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIRDFResource> property = do_QueryInterface(isupports);
|
|
||||||
if (! property) {
|
|
||||||
NS_WARNING("expected a resource");
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* attrname;
|
nsAutoString attrstr;
|
||||||
rv = property->GetValueConst(&attrname);
|
attrs->GetNext(attrstr);
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIAtom> attr = do_GetAtom(attrname);
|
nsAutoString value;
|
||||||
if (! attr)
|
rv = mLocalStore->GetValue(uri, aID, attrstr, value);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIAtom> attr = do_GetAtom(attrstr);
|
||||||
|
if (NS_WARN_IF(!attr)) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
// XXX could hang namespace off here, as well...
|
|
||||||
|
|
||||||
nsCOMPtr<nsIRDFNode> node;
|
|
||||||
rv = mLocalStore->GetTarget(aResource, property, true,
|
|
||||||
getter_AddRefs(node));
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIRDFLiteral> literal = do_QueryInterface(node);
|
|
||||||
if (! literal) {
|
|
||||||
NS_WARNING("expected a literal");
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char16_t* value;
|
|
||||||
rv = literal->GetValueConst(&value);
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
nsDependentString wrapper(value);
|
|
||||||
|
|
||||||
uint32_t cnt = aElements.Count();
|
uint32_t cnt = aElements.Count();
|
||||||
|
|
||||||
for (int32_t i = int32_t(cnt) - 1; i >= 0; --i) {
|
for (int32_t i = int32_t(cnt) - 1; i >= 0; --i) {
|
||||||
nsCOMPtr<nsIContent> element = aElements.SafeObjectAt(i);
|
nsCOMPtr<nsIContent> element = aElements.SafeObjectAt(i);
|
||||||
if (!element)
|
if (!element) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
rv = element->SetAttr(/* XXX */ kNameSpaceID_None,
|
rv = element->SetAttr(kNameSpaceID_None, attr, value, PR_TRUE);
|
||||||
attr,
|
|
||||||
wrapper,
|
|
||||||
true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "nsScriptLoader.h"
|
#include "nsScriptLoader.h"
|
||||||
#include "nsIStreamListener.h"
|
#include "nsIStreamListener.h"
|
||||||
#include "nsICSSLoaderObserver.h"
|
#include "nsICSSLoaderObserver.h"
|
||||||
|
#include "nsIXULStore.h"
|
||||||
|
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
|
|
||||||
@ -259,7 +260,7 @@ protected:
|
|||||||
|
|
||||||
nsresult ApplyPersistentAttributes();
|
nsresult ApplyPersistentAttributes();
|
||||||
nsresult ApplyPersistentAttributesInternal();
|
nsresult ApplyPersistentAttributesInternal();
|
||||||
nsresult ApplyPersistentAttributesToElements(nsIRDFResource* aResource,
|
nsresult ApplyPersistentAttributesToElements(const nsAString &aID,
|
||||||
nsCOMArray<nsIContent>& aElements);
|
nsCOMArray<nsIContent>& aElements);
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
@ -314,10 +315,10 @@ protected:
|
|||||||
// Tracks elements with a 'ref' attribute, or an 'id' attribute where
|
// Tracks elements with a 'ref' attribute, or an 'id' attribute where
|
||||||
// the element's namespace has no registered ID attribute name.
|
// the element's namespace has no registered ID attribute name.
|
||||||
nsTHashtable<nsRefMapEntry> mRefMap;
|
nsTHashtable<nsRefMapEntry> mRefMap;
|
||||||
nsCOMPtr<nsIRDFDataSource> mLocalStore;
|
nsCOMPtr<nsIXULStore> mLocalStore;
|
||||||
bool mApplyingPersistedAttrs;
|
bool mApplyingPersistedAttrs;
|
||||||
bool mIsWritingFastLoad;
|
bool mIsWritingFastLoad;
|
||||||
bool mDocumentLoaded;
|
bool mDocumentLoaded;
|
||||||
/**
|
/**
|
||||||
* Since ResumeWalk is interruptible, it's possible that last
|
* Since ResumeWalk is interruptible, it's possible that last
|
||||||
* stylesheet finishes loading while the PD walk is still in
|
* stylesheet finishes loading while the PD walk is still in
|
||||||
|
@ -186,36 +186,6 @@ nsXULContentUtils::FindChildByTag(nsIContent* aElement,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsXULContentUtils::GetElementResource(nsIContent* aElement, nsIRDFResource** aResult)
|
|
||||||
{
|
|
||||||
// Perform a reverse mapping from an element in the content model
|
|
||||||
// to an RDF resource.
|
|
||||||
nsresult rv;
|
|
||||||
|
|
||||||
char16_t buf[128];
|
|
||||||
nsFixedString id(buf, ArrayLength(buf), 0);
|
|
||||||
|
|
||||||
// Whoa. Why the "id" attribute? What if it's not even a XUL
|
|
||||||
// element? This is totally bogus!
|
|
||||||
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::id, id);
|
|
||||||
if (id.IsEmpty())
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
// Since the element will store its ID attribute as a document-relative value,
|
|
||||||
// we may need to qualify it first...
|
|
||||||
nsCOMPtr<nsIDocument> doc = aElement->GetDocument();
|
|
||||||
NS_ASSERTION(doc, "element is not in any document");
|
|
||||||
if (! doc)
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
rv = nsXULContentUtils::MakeElementResource(doc, id, aResult);
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Note: this routine is similar, yet distinctly different from, nsBookmarksService::GetTextForNode
|
Note: this routine is similar, yet distinctly different from, nsBookmarksService::GetTextForNode
|
||||||
*/
|
*/
|
||||||
@ -287,78 +257,6 @@ nsXULContentUtils::GetTextForNode(nsIRDFNode* aNode, nsAString& aResult)
|
|||||||
return NS_ERROR_UNEXPECTED;
|
return NS_ERROR_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsXULContentUtils::MakeElementURI(nsIDocument* aDocument,
|
|
||||||
const nsAString& aElementID,
|
|
||||||
nsCString& aURI)
|
|
||||||
{
|
|
||||||
// Convert an element's ID to a URI that can be used to refer to
|
|
||||||
// the element in the XUL graph.
|
|
||||||
|
|
||||||
nsIURI *docURI = aDocument->GetDocumentURI();
|
|
||||||
NS_ENSURE_TRUE(docURI, NS_ERROR_UNEXPECTED);
|
|
||||||
|
|
||||||
nsRefPtr<nsIURI> docURIClone;
|
|
||||||
nsresult rv = docURI->Clone(getter_AddRefs(docURIClone));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
rv = docURIClone->SetRef(NS_ConvertUTF16toUTF8(aElementID));
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
|
||||||
return docURIClone->GetSpec(aURI);
|
|
||||||
}
|
|
||||||
|
|
||||||
// docURIClone is apparently immutable. Fine - we can append ref manually.
|
|
||||||
rv = docURI->GetSpec(aURI);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsAutoCString ref;
|
|
||||||
NS_EscapeURL(NS_ConvertUTF16toUTF8(aElementID), esc_FilePath | esc_AlwaysCopy, ref);
|
|
||||||
|
|
||||||
aURI.Append('#');
|
|
||||||
aURI.Append(ref);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsXULContentUtils::MakeElementResource(nsIDocument* aDocument, const nsAString& aID, nsIRDFResource** aResult)
|
|
||||||
{
|
|
||||||
nsresult rv;
|
|
||||||
|
|
||||||
char buf[256];
|
|
||||||
nsFixedCString uri(buf, sizeof(buf), 0);
|
|
||||||
rv = MakeElementURI(aDocument, aID, uri);
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
rv = gRDF->GetResource(uri, aResult);
|
|
||||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create resource");
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsXULContentUtils::MakeElementID(nsIDocument* aDocument,
|
|
||||||
const nsACString& aURI,
|
|
||||||
nsAString& aElementID)
|
|
||||||
{
|
|
||||||
// Convert a URI into an element ID that can be accessed from the
|
|
||||||
// DOM APIs.
|
|
||||||
nsCOMPtr<nsIURI> uri;
|
|
||||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), aURI,
|
|
||||||
aDocument->GetDocumentCharacterSet().get());
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsAutoCString ref;
|
|
||||||
uri->GetRef(ref);
|
|
||||||
CopyUTF8toUTF16(ref, aElementID);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsXULContentUtils::GetResource(int32_t aNameSpaceID, nsIAtom* aAttribute, nsIRDFResource** aResult)
|
nsXULContentUtils::GetResource(int32_t aNameSpaceID, nsIAtom* aAttribute, nsIRDFResource** aResult)
|
||||||
{
|
{
|
||||||
|
@ -115,31 +115,9 @@ public:
|
|||||||
nsIRDFResource* aResource,
|
nsIRDFResource* aResource,
|
||||||
nsIContent** aResult);
|
nsIContent** aResult);
|
||||||
|
|
||||||
static nsresult
|
|
||||||
GetElementResource(nsIContent* aElement, nsIRDFResource** aResult);
|
|
||||||
|
|
||||||
static nsresult
|
static nsresult
|
||||||
GetTextForNode(nsIRDFNode* aNode, nsAString& aResult);
|
GetTextForNode(nsIRDFNode* aNode, nsAString& aResult);
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a URI from the element ID given. This uses aElement as the
|
|
||||||
* ref and aDocument's document URI as the base. If aDocument's document
|
|
||||||
* URI does not support refs, this will throw NS_ERROR_NOT_AVAILABLE.
|
|
||||||
*/
|
|
||||||
static nsresult
|
|
||||||
MakeElementURI(nsIDocument* aDocument, const nsAString& aElementID, nsCString& aURI);
|
|
||||||
|
|
||||||
static nsresult
|
|
||||||
MakeElementResource(nsIDocument* aDocument, const nsAString& aElementID, nsIRDFResource** aResult);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract the element ID from aURI. Note that aURI must be an absolute
|
|
||||||
* URI string in UTF8; the element ID is the ref from the URI. If the
|
|
||||||
* scheme does not support refs, then the ID will be empty.
|
|
||||||
*/
|
|
||||||
static nsresult
|
|
||||||
MakeElementID(nsIDocument* aDocument, const nsACString& aURI, nsAString& aElementID);
|
|
||||||
|
|
||||||
static nsresult
|
static nsresult
|
||||||
GetResource(int32_t aNameSpaceID, nsIAtom* aAttribute, nsIRDFResource** aResult);
|
GetResource(int32_t aNameSpaceID, nsIAtom* aAttribute, nsIRDFResource** aResult);
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#include "nsIContent.h"
|
#include "nsIContent.h"
|
||||||
#include "mozilla/dom/NodeInfo.h"
|
#include "mozilla/dom/NodeInfo.h"
|
||||||
#include "nsIDOMElement.h"
|
#include "nsIDOMElement.h"
|
||||||
#include "nsILocalStore.h"
|
|
||||||
#include "nsIBoxObject.h"
|
#include "nsIBoxObject.h"
|
||||||
#include "nsITreeBoxObject.h"
|
#include "nsITreeBoxObject.h"
|
||||||
#include "nsITreeSelection.h"
|
#include "nsITreeSelection.h"
|
||||||
@ -31,6 +30,7 @@
|
|||||||
#include "nsDOMClassInfoID.h"
|
#include "nsDOMClassInfoID.h"
|
||||||
#include "nsWhitespaceTokenizer.h"
|
#include "nsWhitespaceTokenizer.h"
|
||||||
#include "nsTreeContentView.h"
|
#include "nsTreeContentView.h"
|
||||||
|
#include "nsIXULStore.h"
|
||||||
|
|
||||||
// For security check
|
// For security check
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
@ -139,13 +139,10 @@ protected:
|
|||||||
RemoveMatchesFor(nsTreeRows::Subtree& subtree);
|
RemoveMatchesFor(nsTreeRows::Subtree& subtree);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper methods that determine if the specified container is open.
|
* Helper method that determines if the specified container is open.
|
||||||
*/
|
*/
|
||||||
nsresult
|
bool
|
||||||
IsContainerOpen(nsIXULTemplateResult *aResult, bool* aOpen);
|
IsContainerOpen(nsIXULTemplateResult* aResource);
|
||||||
|
|
||||||
nsresult
|
|
||||||
IsContainerOpen(nsIRDFResource* aResource, bool* aOpen);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A sorting callback for NS_QuickSort().
|
* A sorting callback for NS_QuickSort().
|
||||||
@ -242,6 +239,11 @@ protected:
|
|||||||
* The builder observers.
|
* The builder observers.
|
||||||
*/
|
*/
|
||||||
nsCOMArray<nsIXULTreeBuilderObserver> mObservers;
|
nsCOMArray<nsIXULTreeBuilderObserver> mObservers;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XUL store for holding open container state
|
||||||
|
*/
|
||||||
|
nsCOMPtr<nsIXULStore> mLocalStore;
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
@ -278,6 +280,7 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(nsXULTreeBuilder, nsXULTemplateBuilder,
|
|||||||
mBoxObject,
|
mBoxObject,
|
||||||
mSelection,
|
mSelection,
|
||||||
mPersistStateStore,
|
mPersistStateStore,
|
||||||
|
mLocalStore,
|
||||||
mObservers)
|
mObservers)
|
||||||
|
|
||||||
DOMCI_DATA(XULTreeBuilder, nsXULTreeBuilder)
|
DOMCI_DATA(XULTreeBuilder, nsXULTreeBuilder)
|
||||||
@ -528,8 +531,7 @@ nsXULTreeBuilder::IsContainerOpen(int32_t aIndex, bool* aOpen)
|
|||||||
nsTreeRows::iterator iter = mRows[aIndex];
|
nsTreeRows::iterator iter = mRows[aIndex];
|
||||||
|
|
||||||
if (iter->mContainerState == nsTreeRows::eContainerState_Unknown) {
|
if (iter->mContainerState == nsTreeRows::eContainerState_Unknown) {
|
||||||
bool isOpen;
|
bool isOpen = IsContainerOpen(iter->mMatch->mResult);
|
||||||
IsContainerOpen(iter->mMatch->mResult, &isOpen);
|
|
||||||
|
|
||||||
iter->mContainerState = isOpen
|
iter->mContainerState = isOpen
|
||||||
? nsTreeRows::eContainerState_Open
|
? nsTreeRows::eContainerState_Open
|
||||||
@ -757,42 +759,16 @@ nsXULTreeBuilder::SetTree(nsITreeBoxObject* aTree)
|
|||||||
}
|
}
|
||||||
NS_ENSURE_TRUE(mRoot, NS_ERROR_NOT_INITIALIZED);
|
NS_ENSURE_TRUE(mRoot, NS_ERROR_NOT_INITIALIZED);
|
||||||
|
|
||||||
// Is our root's principal trusted?
|
// Only use the XUL store if the root's principal is trusted.
|
||||||
bool isTrusted = false;
|
bool isTrusted = false;
|
||||||
nsresult rv = IsSystemPrincipal(mRoot->NodePrincipal(), &isTrusted);
|
nsresult rv = IsSystemPrincipal(mRoot->NodePrincipal(), &isTrusted);
|
||||||
if (NS_SUCCEEDED(rv) && isTrusted) {
|
if (NS_SUCCEEDED(rv) && isTrusted) {
|
||||||
// Get the datasource we intend to use to remember open state.
|
mLocalStore = do_GetService("@mozilla.org/xul/xulstore;1");
|
||||||
nsAutoString datasourceStr;
|
if(NS_WARN_IF(!mLocalStore)){
|
||||||
mRoot->GetAttr(kNameSpaceID_None, nsGkAtoms::statedatasource, datasourceStr);
|
return NS_ERROR_NOT_INITIALIZED;
|
||||||
|
|
||||||
// since we are trusted, use the user specified datasource
|
|
||||||
// if non specified, use localstore, which gives us
|
|
||||||
// persistence across sessions
|
|
||||||
if (! datasourceStr.IsEmpty()) {
|
|
||||||
gRDFService->GetDataSource(NS_ConvertUTF16toUTF8(datasourceStr).get(),
|
|
||||||
getter_AddRefs(mPersistStateStore));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
gRDFService->GetDataSource("rdf:local-store",
|
|
||||||
getter_AddRefs(mPersistStateStore));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Either no specific datasource was specified, or we failed
|
|
||||||
// to get one because we are not trusted.
|
|
||||||
//
|
|
||||||
// XXX if it were possible to ``write an arbitrary datasource
|
|
||||||
// back'', then we could also allow an untrusted document to
|
|
||||||
// use a statedatasource from the same codebase.
|
|
||||||
if (! mPersistStateStore) {
|
|
||||||
mPersistStateStore =
|
|
||||||
do_CreateInstance("@mozilla.org/rdf/datasource;1?name=in-memory-datasource");
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_ASSERTION(mPersistStateStore, "failed to get a persistent state store");
|
|
||||||
if (! mPersistStateStore)
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
Rebuild();
|
Rebuild();
|
||||||
|
|
||||||
EnsureSortVariables();
|
EnsureSortVariables();
|
||||||
@ -830,34 +806,36 @@ nsXULTreeBuilder::ToggleOpenState(int32_t aIndex)
|
|||||||
observer->OnToggleOpenState(aIndex);
|
observer->OnToggleOpenState(aIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mPersistStateStore) {
|
if (mLocalStore && mRoot) {
|
||||||
bool isOpen;
|
bool isOpen;
|
||||||
IsContainerOpen(aIndex, &isOpen);
|
IsContainerOpen(aIndex, &isOpen);
|
||||||
|
|
||||||
nsCOMPtr<nsIRDFResource> container;
|
nsIDocument* doc = mRoot->GetDocument();
|
||||||
GetResourceFor(aIndex, getter_AddRefs(container));
|
if (!doc) {
|
||||||
if (! container)
|
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
bool hasProperty;
|
nsIURI* docURI = doc->GetDocumentURI();
|
||||||
IsContainerOpen(container, &hasProperty);
|
nsTreeRows::Row& row = *(mRows[aIndex]);
|
||||||
|
nsAutoString nodeid;
|
||||||
|
nsresult rv = row.mMatch->mResult->GetId(nodeid);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoCString utf8uri;
|
||||||
|
rv = docURI->GetSpec(utf8uri);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
NS_ConvertUTF8toUTF16 uri(utf8uri);
|
||||||
|
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
if (hasProperty) {
|
mLocalStore->RemoveValue(uri, nodeid, NS_LITERAL_STRING("open"));
|
||||||
mPersistStateStore->Unassert(container,
|
|
||||||
nsXULContentUtils::NC_open,
|
|
||||||
nsXULContentUtils::true_);
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseContainer(aIndex);
|
CloseContainer(aIndex);
|
||||||
}
|
} else {
|
||||||
else {
|
mLocalStore->SetValue(uri, nodeid, NS_LITERAL_STRING("open"),
|
||||||
if (! hasProperty) {
|
NS_LITERAL_STRING("true"));
|
||||||
mPersistStateStore->Assert(container,
|
|
||||||
nsXULContentUtils::NC_open,
|
|
||||||
nsXULContentUtils::true_,
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
|
|
||||||
OpenContainer(aIndex, result);
|
OpenContainer(aIndex, result);
|
||||||
}
|
}
|
||||||
@ -1225,10 +1203,9 @@ nsXULTreeBuilder::ReplaceMatch(nsIXULTemplateResult* aOldResult,
|
|||||||
if (NS_FAILED(rv) || ! mayProcessChildren) return NS_OK;
|
if (NS_FAILED(rv) || ! mayProcessChildren) return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool open;
|
if (IsContainerOpen(result)) {
|
||||||
IsContainerOpen(result, &open);
|
|
||||||
if (open)
|
|
||||||
OpenContainer(iter.GetRowIndex(), result);
|
OpenContainer(iter.GetRowIndex(), result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1636,9 +1613,7 @@ nsXULTreeBuilder::OpenSubtreeForQuerySet(nsTreeRows::Subtree* aSubtree,
|
|||||||
|
|
||||||
// If this is open, then remember it so we can recursively add
|
// If this is open, then remember it so we can recursively add
|
||||||
// *its* rows to the tree.
|
// *its* rows to the tree.
|
||||||
bool isOpen = false;
|
if (IsContainerOpen(nextresult)) {
|
||||||
IsContainerOpen(nextresult, &isOpen);
|
|
||||||
if (isOpen) {
|
|
||||||
if (open.AppendElement(count) == nullptr)
|
if (open.AppendElement(count) == nullptr)
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
@ -1722,36 +1697,42 @@ nsXULTreeBuilder::RemoveMatchesFor(nsTreeRows::Subtree& subtree)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsXULTreeBuilder::IsContainerOpen(nsIXULTemplateResult *aResult, bool* aOpen)
|
bool
|
||||||
|
nsXULTreeBuilder::IsContainerOpen(nsIXULTemplateResult *aResult)
|
||||||
{
|
{
|
||||||
// items are never open if recursion is disabled
|
// items are never open if recursion is disabled
|
||||||
if ((mFlags & eDontRecurse) && aResult != mRootResult) {
|
if ((mFlags & eDontRecurse) && aResult != mRootResult) {
|
||||||
*aOpen = false;
|
return false;
|
||||||
return NS_OK;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIRDFResource> id;
|
if (!mLocalStore) {
|
||||||
nsresult rv = GetResultResource(aResult, getter_AddRefs(id));
|
return false;
|
||||||
if (NS_FAILED(rv))
|
}
|
||||||
return rv;
|
|
||||||
|
|
||||||
return IsContainerOpen(id, aOpen);
|
nsIDocument* doc = mRoot->GetDocument();
|
||||||
}
|
if (!doc) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsIURI* docURI = doc->GetDocumentURI();
|
||||||
nsXULTreeBuilder::IsContainerOpen(nsIRDFResource* aResource, bool* aOpen)
|
|
||||||
{
|
|
||||||
if (mPersistStateStore)
|
|
||||||
mPersistStateStore->HasAssertion(aResource,
|
|
||||||
nsXULContentUtils::NC_open,
|
|
||||||
nsXULContentUtils::true_,
|
|
||||||
true,
|
|
||||||
aOpen);
|
|
||||||
else
|
|
||||||
*aOpen = false;
|
|
||||||
|
|
||||||
return NS_OK;
|
nsAutoString nodeid;
|
||||||
|
nsresult rv = aResult->GetId(nodeid);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoCString utf8uri;
|
||||||
|
rv = docURI->GetSpec(utf8uri);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
NS_ConvertUTF8toUTF16 uri(utf8uri);
|
||||||
|
|
||||||
|
nsAutoString val;
|
||||||
|
mLocalStore->GetValue(uri, nodeid, NS_LITERAL_STRING("open"), val);
|
||||||
|
return val.EqualsLiteral("true");
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -249,6 +249,7 @@
|
|||||||
@BINPATH@/components/toolkit_finalizationwitness.xpt
|
@BINPATH@/components/toolkit_finalizationwitness.xpt
|
||||||
@BINPATH@/components/toolkit_formautofill.xpt
|
@BINPATH@/components/toolkit_formautofill.xpt
|
||||||
@BINPATH@/components/toolkit_osfile.xpt
|
@BINPATH@/components/toolkit_osfile.xpt
|
||||||
|
@BINPATH@/components/toolkit_xulstore.xpt
|
||||||
@BINPATH@/components/toolkitprofile.xpt
|
@BINPATH@/components/toolkitprofile.xpt
|
||||||
#ifdef MOZ_ENABLE_XREMOTE
|
#ifdef MOZ_ENABLE_XREMOTE
|
||||||
@BINPATH@/components/toolkitremote.xpt
|
@BINPATH@/components/toolkitremote.xpt
|
||||||
@ -395,6 +396,8 @@
|
|||||||
@BINPATH@/components/servicesComponents.manifest
|
@BINPATH@/components/servicesComponents.manifest
|
||||||
@BINPATH@/components/TelemetryStartup.js
|
@BINPATH@/components/TelemetryStartup.js
|
||||||
@BINPATH@/components/TelemetryStartup.manifest
|
@BINPATH@/components/TelemetryStartup.manifest
|
||||||
|
@BINPATH@/components/XULStore.js
|
||||||
|
@BINPATH@/components/XULStore.manifest
|
||||||
@BINPATH@/components/Webapps.js
|
@BINPATH@/components/Webapps.js
|
||||||
@BINPATH@/components/Webapps.manifest
|
@BINPATH@/components/Webapps.manifest
|
||||||
@BINPATH@/components/AppsService.js
|
@BINPATH@/components/AppsService.js
|
||||||
|
@ -49,6 +49,7 @@ DIRS += [
|
|||||||
'viewsource',
|
'viewsource',
|
||||||
'workerloader',
|
'workerloader',
|
||||||
'workerlz4',
|
'workerlz4',
|
||||||
|
'xulstore'
|
||||||
]
|
]
|
||||||
|
|
||||||
if CONFIG['MOZ_CRASHREPORTER']:
|
if CONFIG['MOZ_CRASHREPORTER']:
|
||||||
|
@ -3584,7 +3584,7 @@ const int64_t UNDEFINED_URN_VALUE = -1;
|
|||||||
|
|
||||||
// Create a urn (like
|
// Create a urn (like
|
||||||
// urn:places-persist:place:group=0&group=1&sort=1&type=1,,%28local%20files%29)
|
// urn:places-persist:place:group=0&group=1&sort=1&type=1,,%28local%20files%29)
|
||||||
// to be used to persist the open state of this container in localstore.rdf
|
// to be used to persist the open state of this container
|
||||||
nsresult
|
nsresult
|
||||||
CreatePlacesPersistURN(nsNavHistoryQueryResultNode *aResultNode,
|
CreatePlacesPersistURN(nsNavHistoryQueryResultNode *aResultNode,
|
||||||
int64_t aValue, const nsCString& aTitle, nsCString& aURN)
|
int64_t aValue, const nsCString& aTitle, nsCString& aURN)
|
||||||
|
336
toolkit/components/xulstore/XULStore.js
Normal file
336
toolkit/components/xulstore/XULStore.js
Normal file
@ -0,0 +1,336 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
const Cc = Components.classes;
|
||||||
|
const Ci = Components.interfaces;
|
||||||
|
const Cr = Components.results;
|
||||||
|
const Cu = Components.utils;
|
||||||
|
|
||||||
|
// Enables logging and shorter save intervals.
|
||||||
|
const debugMode = false;
|
||||||
|
|
||||||
|
// Delay when a change is made to when the file is saved.
|
||||||
|
// 30 seconds normally, or 3 seconds for testing
|
||||||
|
const WRITE_DELAY_MS = (debugMode ? 3 : 30) * 1000;
|
||||||
|
|
||||||
|
const XULSTORE_CONTRACTID = "@mozilla.org/xul/xulstore;1";
|
||||||
|
const XULSTORE_CID = Components.ID("{6f46b6f4-c8b1-4bd4-a4fa-9ebbed0753ea}");
|
||||||
|
const STOREDB_FILENAME = "xulstore.json";
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
Cu.import("resource://gre/modules/Task.jsm");
|
||||||
|
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm");
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
|
||||||
|
|
||||||
|
function XULStore() {
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
XULStore.prototype = {
|
||||||
|
classID: XULSTORE_CID,
|
||||||
|
classInfo: XPCOMUtils.generateCI({classID: XULSTORE_CID,
|
||||||
|
contractID: XULSTORE_CONTRACTID,
|
||||||
|
classDescription: "XULStore",
|
||||||
|
interfaces: [Ci.nsIXULStore]}),
|
||||||
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsIXULStore,
|
||||||
|
Ci.nsISupportsWeakReference]),
|
||||||
|
_xpcom_factory: XPCOMUtils.generateSingletonFactory(XULStore),
|
||||||
|
|
||||||
|
/* ---------- private members ---------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The format of _data is _data[docuri][elementid][attribute]. For example:
|
||||||
|
* {
|
||||||
|
* "chrome://blah/foo.xul" : {
|
||||||
|
* "main-window" : { aaa : 1, bbb : "c" },
|
||||||
|
* "barColumn" : { ddd : 9, eee : "f" },
|
||||||
|
* },
|
||||||
|
*
|
||||||
|
* "chrome://foopy/b.xul" : { ... },
|
||||||
|
* ...
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
_data: {},
|
||||||
|
_storeFile: null,
|
||||||
|
_needsSaving: false,
|
||||||
|
_saveAllowed: true,
|
||||||
|
_writeTimer: Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer),
|
||||||
|
_writeTimerInitialized: false,
|
||||||
|
|
||||||
|
init: function () {
|
||||||
|
Services.obs.addObserver(this, "profile-before-change", true);
|
||||||
|
|
||||||
|
this._storeFile = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||||
|
this._storeFile.append(STOREDB_FILENAME);
|
||||||
|
|
||||||
|
if (!this._storeFile.exists()) {
|
||||||
|
this.import();
|
||||||
|
} else {
|
||||||
|
this.readFile();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
observe: function(subject, topic, data) {
|
||||||
|
if (topic == "profile-before-change") {
|
||||||
|
this.writeFile();
|
||||||
|
this._saveAllowed = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal function for logging debug messages to the Error Console window
|
||||||
|
*/
|
||||||
|
log: function (message) {
|
||||||
|
if (!debugMode)
|
||||||
|
return;
|
||||||
|
dump("XULStore: " + message + "\n");
|
||||||
|
Services.console.logStringMessage("XULStore: " + message);
|
||||||
|
},
|
||||||
|
|
||||||
|
import: function() {
|
||||||
|
let localStoreFile = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||||
|
|
||||||
|
localStoreFile.append("localstore.rdf");
|
||||||
|
if (!localStoreFile.exists()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RDF = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
|
||||||
|
const persistKey = RDF.GetResource("http://home.netscape.com/NC-rdf#persist");
|
||||||
|
|
||||||
|
this.log("Import localstore from " + localStoreFile.path);
|
||||||
|
|
||||||
|
let localStoreURI = Services.io.newFileURI(localStoreFile).spec;
|
||||||
|
let localStore = RDF.GetDataSourceBlocking(localStoreURI);
|
||||||
|
let resources = localStore.GetAllResources();
|
||||||
|
|
||||||
|
while (resources.hasMoreElements()) {
|
||||||
|
let resource = resources.getNext().QueryInterface(Ci.nsIRDFResource);
|
||||||
|
let uri;
|
||||||
|
|
||||||
|
try {
|
||||||
|
uri = NetUtil.newURI(resource.ValueUTF8);
|
||||||
|
} catch(ex) {
|
||||||
|
continue; // skip invalid uris
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this has a ref, then this is an attribute reference. Otherwise,
|
||||||
|
// this is a document reference.
|
||||||
|
if (!uri.hasRef)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Verify that there the persist key is connected up.
|
||||||
|
let docURI = uri.specIgnoringRef;
|
||||||
|
|
||||||
|
if (!localStore.HasAssertion(RDF.GetResource(docURI), persistKey, resource, true))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
let id = uri.ref;
|
||||||
|
let attrs = localStore.ArcLabelsOut(resource);
|
||||||
|
|
||||||
|
while (attrs.hasMoreElements()) {
|
||||||
|
let attr = attrs.getNext().QueryInterface(Ci.nsIRDFResource);
|
||||||
|
let value = localStore.GetTarget(resource, attr, true);
|
||||||
|
|
||||||
|
if (value instanceof Ci.nsIRDFLiteral) {
|
||||||
|
this.setValue(docURI, id, attr.ValueUTF8, value.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
readFile: function() {
|
||||||
|
const MODE_RDONLY = 0x01;
|
||||||
|
const FILE_PERMS = 0600;
|
||||||
|
|
||||||
|
let stream = Cc["@mozilla.org/network/file-input-stream;1"].
|
||||||
|
createInstance(Ci.nsIFileInputStream);
|
||||||
|
let json = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON);
|
||||||
|
try {
|
||||||
|
stream.init(this._storeFile, MODE_RDONLY, FILE_PERMS, 0);
|
||||||
|
this._data = json.decodeFromStream(stream, stream.available());
|
||||||
|
} catch(e) {
|
||||||
|
this.log("Error reading JSON: " + e);
|
||||||
|
// Ignore problem, we'll just continue on with an empty dataset.
|
||||||
|
} finally {
|
||||||
|
stream.close();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
writeFile: Task.async(function* () {
|
||||||
|
if (!this._needsSaving)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._needsSaving = false;
|
||||||
|
|
||||||
|
this.log("Writing to xulstore.json");
|
||||||
|
|
||||||
|
try {
|
||||||
|
let data = JSON.stringify(this._data);
|
||||||
|
let encoder = new TextEncoder();
|
||||||
|
|
||||||
|
data = encoder.encode(data);
|
||||||
|
yield OS.File.writeAtomic(this._storeFile.path, data,
|
||||||
|
{ tmpPath: this._storeFile.path + ".tmp" });
|
||||||
|
} catch (e) {
|
||||||
|
this.log("Failed to write xulstore.json: " + e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
markAsChanged: function() {
|
||||||
|
this._needsSaving = true;
|
||||||
|
if (this._writeTimerInitialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let callback = () => {
|
||||||
|
this._writeTimerInitialized = false;
|
||||||
|
this.writeFile();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Don't write the file more than once every 30 seconds.
|
||||||
|
this._writeTimerInitialized = true;
|
||||||
|
this._writeTimer.initWithCallback(callback, WRITE_DELAY_MS, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- interface implementation ---------- */
|
||||||
|
|
||||||
|
setValue: function (docURI, id, attr, value) {
|
||||||
|
this.log("Saving " + attr + "=" + value + " for id=" + id + ", doc=" + docURI);
|
||||||
|
|
||||||
|
if (!this._saveAllowed) {
|
||||||
|
Services.console.logStringMessage("XULStore: Changes after profile-before-change are ignored!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// bug 319846 -- don't save really long attributes or values.
|
||||||
|
if (id.length > 1024 || attr.length > 1024 || value.length > 1024)
|
||||||
|
throw Components.Exception("id, attribute, or value too long", Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||||
|
|
||||||
|
let obj = this._data;
|
||||||
|
if (!(docURI in obj)) {
|
||||||
|
obj[docURI] = {};
|
||||||
|
}
|
||||||
|
obj = obj[docURI];
|
||||||
|
if (!(id in obj)) {
|
||||||
|
obj[id] = {};
|
||||||
|
}
|
||||||
|
obj = obj[id];
|
||||||
|
|
||||||
|
// Don't set the value if it is already set to avoid saving the file.
|
||||||
|
if (attr in obj && obj[attr] == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
obj[attr] = value; //IE, this._data[docURI][id][attr] = value;
|
||||||
|
|
||||||
|
this.markAsChanged();
|
||||||
|
},
|
||||||
|
|
||||||
|
hasValue: function (docURI, id, attr) {
|
||||||
|
this.log("has store value for id=" + id + ", attr=" + attr + ", doc=" + docURI);
|
||||||
|
|
||||||
|
let ids = this._data[docURI];
|
||||||
|
if (ids) {
|
||||||
|
let attrs = ids[id];
|
||||||
|
if (attrs) {
|
||||||
|
return attr in attrs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
getValue: function (docURI, id, attr) {
|
||||||
|
this.log("get store value for id=" + id + ", attr=" + attr + ", doc=" + docURI);
|
||||||
|
|
||||||
|
let ids = this._data[docURI];
|
||||||
|
if (ids) {
|
||||||
|
let attrs = ids[id];
|
||||||
|
if (attrs) {
|
||||||
|
return attrs[attr] || "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
},
|
||||||
|
|
||||||
|
removeValue: function (docURI, id, attr) {
|
||||||
|
this.log("remove store value for id=" + id + ", attr=" + attr + ", doc=" + docURI);
|
||||||
|
|
||||||
|
if (!this._saveAllowed) {
|
||||||
|
Services.console.logStringMessage("XULStore: Changes after profile-before-change are ignored!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ids = this._data[docURI];
|
||||||
|
if (ids) {
|
||||||
|
let attrs = ids[id];
|
||||||
|
if (attrs && attr in attrs) {
|
||||||
|
delete attrs[attr];
|
||||||
|
|
||||||
|
if (Object.getOwnPropertyNames(attrs).length == 0) {
|
||||||
|
delete ids[id];
|
||||||
|
|
||||||
|
if (Object.getOwnPropertyNames(ids).length == 0) {
|
||||||
|
delete this._data[docURI];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.markAsChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getIDsEnumerator: function (docURI) {
|
||||||
|
this.log("Getting ID enumerator for doc=" + docURI);
|
||||||
|
|
||||||
|
if (!(docURI in this._data))
|
||||||
|
return new nsStringEnumerator([]);
|
||||||
|
|
||||||
|
let result = [];
|
||||||
|
let ids = this._data[docURI];
|
||||||
|
if (ids) {
|
||||||
|
for (let id in this._data[docURI]) {
|
||||||
|
result.push(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new nsStringEnumerator(result);
|
||||||
|
},
|
||||||
|
|
||||||
|
getAttributeEnumerator: function (docURI, id) {
|
||||||
|
this.log("Getting attribute enumerator for id=" + id + ", doc=" + docURI);
|
||||||
|
|
||||||
|
if (!(docURI in this._data) || !(id in this._data[docURI]))
|
||||||
|
return new nsStringEnumerator([]);
|
||||||
|
|
||||||
|
let attrs = [];
|
||||||
|
for (let attr in this._data[docURI][id]) {
|
||||||
|
attrs.push(attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new nsStringEnumerator(attrs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function nsStringEnumerator(items) {
|
||||||
|
this._items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsStringEnumerator.prototype = {
|
||||||
|
QueryInterface : XPCOMUtils.generateQI([Ci.nsIStringEnumerator]),
|
||||||
|
_nextIndex : 0,
|
||||||
|
hasMore: function() {
|
||||||
|
return this._nextIndex < this._items.length;
|
||||||
|
},
|
||||||
|
getNext : function() {
|
||||||
|
if (!this.hasMore())
|
||||||
|
throw Cr.NS_ERROR_NOT_AVAILABLE;
|
||||||
|
return this._items[this._nextIndex++];
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([XULStore]);
|
2
toolkit/components/xulstore/XULStore.manifest
Normal file
2
toolkit/components/xulstore/XULStore.manifest
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
component {6f46b6f4-c8b1-4bd4-a4fa-9ebbed0753ea} XULStore.js
|
||||||
|
contract @mozilla.org/xul/xulstore;1 {6f46b6f4-c8b1-4bd4-a4fa-9ebbed0753ea}
|
18
toolkit/components/xulstore/moz.build
Normal file
18
toolkit/components/xulstore/moz.build
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||||
|
# vim: set filetype=python:
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
TEST_DIRS += ['tests']
|
||||||
|
|
||||||
|
XPIDL_SOURCES += [
|
||||||
|
'nsIXULStore.idl',
|
||||||
|
]
|
||||||
|
|
||||||
|
XPIDL_MODULE = 'toolkit_xulstore'
|
||||||
|
|
||||||
|
EXTRA_COMPONENTS += [
|
||||||
|
'XULStore.js',
|
||||||
|
'XULStore.manifest',
|
||||||
|
]
|
75
toolkit/components/xulstore/nsIXULStore.idl
Normal file
75
toolkit/components/xulstore/nsIXULStore.idl
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "nsISupports.idl"
|
||||||
|
|
||||||
|
interface nsIStringEnumerator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The XUL store is used to store information related to a XUL document/application.
|
||||||
|
* Typically it is used to store the persisted state for the document, such as
|
||||||
|
* window location, toolbars that are open and nodes that are open and closed in a tree.
|
||||||
|
*
|
||||||
|
* The data is serialized to [profile directory]/xulstore.json
|
||||||
|
*/
|
||||||
|
[scriptable, uuid(987c4b35-c426-4dd7-ad49-3c9fa4c65d20)]
|
||||||
|
|
||||||
|
interface nsIXULStore: nsISupports
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Sets a value in the store.
|
||||||
|
*
|
||||||
|
* @param doc - document URI
|
||||||
|
* @param id - identifier of the node
|
||||||
|
* @param attr - attribute to store
|
||||||
|
* @param value - value of the attribute
|
||||||
|
*/
|
||||||
|
void setValue(in AString doc, in AString id, in AString attr, in AString value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the store contains a value for attr.
|
||||||
|
*
|
||||||
|
* @param doc - URI of the document
|
||||||
|
* @param id - identifier of the node
|
||||||
|
* @param attr - attribute
|
||||||
|
*/
|
||||||
|
bool hasValue(in AString doc, in AString id, in AString attr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a value in the store, or an empty string if it does not exist.
|
||||||
|
*
|
||||||
|
* @param doc - document URI
|
||||||
|
* @param id - identifier of the node
|
||||||
|
* @param attr - attribute to retrieve
|
||||||
|
*
|
||||||
|
* @returns the value of the attribute
|
||||||
|
*/
|
||||||
|
AString getValue(in AString doc, in AString id, in AString attr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a value in the store.
|
||||||
|
*
|
||||||
|
* @param doc - document URI
|
||||||
|
* @param id - identifier of the node
|
||||||
|
* @param attr - attribute to remove
|
||||||
|
*/
|
||||||
|
void removeValue(in AString doc, in AString id, in AString attr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterates over all of the ids associated with a given document uri that
|
||||||
|
* have stored data.
|
||||||
|
*
|
||||||
|
* @param doc - document URI
|
||||||
|
*/
|
||||||
|
nsIStringEnumerator getIDsEnumerator(in AString doc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterates over all of the attributes associated with a given document uri
|
||||||
|
* and id that have stored data.
|
||||||
|
*
|
||||||
|
* @param doc - document URI
|
||||||
|
* @param id - identifier of the node
|
||||||
|
*/
|
||||||
|
nsIStringEnumerator getAttributeEnumerator(in AString doc, in AString id);
|
||||||
|
};
|
142
toolkit/components/xulstore/tests/chrome/animals.rdf
Normal file
142
toolkit/components/xulstore/tests/chrome/animals.rdf
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
|
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:NC="http://home.netscape.com/NC-rdf#"
|
||||||
|
xmlns:ANIMALS="http://www.some-fictitious-zoo.com/rdf#">
|
||||||
|
|
||||||
|
<ANIMALS:Class RDF:about="http://www.some-fictitious-zoo.com/arachnids">
|
||||||
|
<ANIMALS:name>Arachnids</ANIMALS:name>
|
||||||
|
</ANIMALS:Class>
|
||||||
|
|
||||||
|
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/arachnids/tarantula">
|
||||||
|
<ANIMALS:name>Tarantula</ANIMALS:name>
|
||||||
|
</RDF:Description>
|
||||||
|
|
||||||
|
<ANIMALS:Class RDF:about="http://www.some-fictitious-zoo.com/birds">
|
||||||
|
<ANIMALS:name>Birds</ANIMALS:name>
|
||||||
|
</ANIMALS:Class>
|
||||||
|
|
||||||
|
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/birds/emu">
|
||||||
|
<ANIMALS:name>Emu</ANIMALS:name>
|
||||||
|
</RDF:Description>
|
||||||
|
|
||||||
|
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/birds/barnowl">
|
||||||
|
<ANIMALS:name>Barn Owl</ANIMALS:name>
|
||||||
|
</RDF:Description>
|
||||||
|
|
||||||
|
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/birds/raven">
|
||||||
|
<ANIMALS:name>Raven</ANIMALS:name>
|
||||||
|
</RDF:Description>
|
||||||
|
|
||||||
|
<ANIMALS:Class RDF:about="http://www.some-fictitious-zoo.com/crustaceans">
|
||||||
|
<ANIMALS:name>Crustaceans</ANIMALS:name>
|
||||||
|
</ANIMALS:Class>
|
||||||
|
|
||||||
|
<ANIMALS:Class RDF:about="http://www.some-fictitious-zoo.com/fish">
|
||||||
|
<ANIMALS:name>Fish</ANIMALS:name>
|
||||||
|
</ANIMALS:Class>
|
||||||
|
|
||||||
|
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/fish/cod">
|
||||||
|
<ANIMALS:name>Cod</ANIMALS:name>
|
||||||
|
</RDF:Description>
|
||||||
|
|
||||||
|
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/fish/swordfish">
|
||||||
|
<ANIMALS:name>Swordfish</ANIMALS:name>
|
||||||
|
</RDF:Description>
|
||||||
|
|
||||||
|
<ANIMALS:Class RDF:about="http://www.some-fictitious-zoo.com/mammals">
|
||||||
|
<ANIMALS:name>Mammals</ANIMALS:name>
|
||||||
|
</ANIMALS:Class>
|
||||||
|
|
||||||
|
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/mammals/lion">
|
||||||
|
<ANIMALS:name>Lion</ANIMALS:name>
|
||||||
|
</RDF:Description>
|
||||||
|
|
||||||
|
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/mammals/hippopotamus">
|
||||||
|
<ANIMALS:name>HIPPOPOTAMUS</ANIMALS:name>
|
||||||
|
</RDF:Description>
|
||||||
|
|
||||||
|
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/mammals/africanelephant">
|
||||||
|
<ANIMALS:name>African Elephant</ANIMALS:name>
|
||||||
|
</RDF:Description>
|
||||||
|
|
||||||
|
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/mammals/llama">
|
||||||
|
<ANIMALS:name>LLAMA</ANIMALS:name>
|
||||||
|
</RDF:Description>
|
||||||
|
|
||||||
|
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/mammals/polarbear">
|
||||||
|
<ANIMALS:name>Polar Bear</ANIMALS:name>
|
||||||
|
</RDF:Description>
|
||||||
|
|
||||||
|
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/mammals/aardvark">
|
||||||
|
<ANIMALS:name>aardvark</ANIMALS:name>
|
||||||
|
</RDF:Description>
|
||||||
|
|
||||||
|
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/mammals/ninebandedarmadillo">
|
||||||
|
<ANIMALS:name>Nine-banded Armadillo</ANIMALS:name>
|
||||||
|
</RDF:Description>
|
||||||
|
|
||||||
|
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/mammals/gorilla">
|
||||||
|
<ANIMALS:name>Gorilla</ANIMALS:name>
|
||||||
|
</RDF:Description>
|
||||||
|
|
||||||
|
<ANIMALS:Class RDF:about="http://www.some-fictitious-zoo.com/reptiles">
|
||||||
|
<ANIMALS:name>Reptiles</ANIMALS:name>
|
||||||
|
</ANIMALS:Class>
|
||||||
|
|
||||||
|
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/reptiles/anaconda">
|
||||||
|
<ANIMALS:name>Anaconda</ANIMALS:name>
|
||||||
|
</RDF:Description>
|
||||||
|
|
||||||
|
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/reptiles/chameleon">
|
||||||
|
<ANIMALS:name>Chameleon</ANIMALS:name>
|
||||||
|
</RDF:Description>
|
||||||
|
|
||||||
|
<RDF:Seq RDF:about="http://www.some-fictitious-zoo.com/some-animals" ANIMALS:name="Zoo Animals">
|
||||||
|
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/arachnids"/>
|
||||||
|
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/birds"/>
|
||||||
|
</RDF:Seq>
|
||||||
|
|
||||||
|
<RDF:Seq RDF:about="http://www.some-fictitious-zoo.com/all-animals" ANIMALS:name="Zoo Animals">
|
||||||
|
<RDF:li>
|
||||||
|
<RDF:Seq RDF:about="http://www.some-fictitious-zoo.com/arachnids">
|
||||||
|
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/arachnids/tarantula"/>
|
||||||
|
</RDF:Seq>
|
||||||
|
</RDF:li>
|
||||||
|
<RDF:li>
|
||||||
|
<RDF:Seq RDF:about="http://www.some-fictitious-zoo.com/birds">
|
||||||
|
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/birds/emu"/>
|
||||||
|
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/birds/barnowl"/>
|
||||||
|
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/birds/raven"/>
|
||||||
|
</RDF:Seq>
|
||||||
|
</RDF:li>
|
||||||
|
<RDF:li>
|
||||||
|
<RDF:Seq RDF:about="http://www.some-fictitious-zoo.com/crustaceans"/>
|
||||||
|
</RDF:li>
|
||||||
|
<RDF:li>
|
||||||
|
<RDF:Seq RDF:about="http://www.some-fictitious-zoo.com/fish">
|
||||||
|
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/fish/cod"/>
|
||||||
|
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/fish/swordfish"/>
|
||||||
|
</RDF:Seq>
|
||||||
|
</RDF:li>
|
||||||
|
<RDF:li>
|
||||||
|
<RDF:Seq RDF:about="http://www.some-fictitious-zoo.com/mammals">
|
||||||
|
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/mammals/lion"/>
|
||||||
|
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/mammals/hippopotamus"/>
|
||||||
|
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/mammals/africanelephant"/>
|
||||||
|
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/mammals/llama"/>
|
||||||
|
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/mammals/polarbear"/>
|
||||||
|
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/mammals/aardvark"/>
|
||||||
|
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/mammals/ninebandedarmadillo"/>
|
||||||
|
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/mammals/gorilla"/>
|
||||||
|
</RDF:Seq>
|
||||||
|
</RDF:li>
|
||||||
|
<RDF:li>
|
||||||
|
<RDF:Seq RDF:about="http://www.some-fictitious-zoo.com/reptiles">
|
||||||
|
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/reptiles/anaconda"/>
|
||||||
|
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/reptiles/chameleon"/>
|
||||||
|
</RDF:Seq>
|
||||||
|
</RDF:li>
|
||||||
|
</RDF:Seq>
|
||||||
|
|
||||||
|
</RDF:RDF>
|
6
toolkit/components/xulstore/tests/chrome/chrome.ini
Normal file
6
toolkit/components/xulstore/tests/chrome/chrome.ini
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[DEFAULT]
|
||||||
|
support-files =
|
||||||
|
window_persistence.xul
|
||||||
|
animals.rdf
|
||||||
|
|
||||||
|
[test_persistence.xul]
|
@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||||
|
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
|
||||||
|
|
||||||
|
<window title="Persistence Tests"
|
||||||
|
onload="runTest()"
|
||||||
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||||
|
|
||||||
|
<script type="application/javascript"
|
||||||
|
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
function runTest() {
|
||||||
|
window.openDialog("window_persistence.xul", "_blank", "chrome", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function windowOpened() {
|
||||||
|
window.openDialog("window_persistence.xul", "_blank", "chrome", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testDone() {
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<p id="display"/>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</window>
|
@ -0,0 +1,98 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||||
|
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
|
||||||
|
|
||||||
|
<window title="Persistence Tests"
|
||||||
|
onload="opened()"
|
||||||
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||||
|
persist="screenX screenY width height">
|
||||||
|
|
||||||
|
<button id="button1" label="Button1" persist="value"/>
|
||||||
|
<button id="button2" label="Button2" value="Normal" persist="value"/>
|
||||||
|
|
||||||
|
<tree id="tree" datasources="animals.rdf" ref="http://www.some-fictitious-zoo.com/all-animals"
|
||||||
|
flags="dont-build-content" width="200" height="200">
|
||||||
|
<treecols orient="horizontal" id="treecols">
|
||||||
|
<treecol id="treecol" primary="true" label="Name" flex="1"/>
|
||||||
|
</treecols>
|
||||||
|
<template id="template">
|
||||||
|
<treechildren>
|
||||||
|
<treeitem uri="rdf:*">
|
||||||
|
<treerow>
|
||||||
|
<treecell label="rdf:http://www.some-fictitious-zoo.com/rdf#name"/>
|
||||||
|
<treecell/>
|
||||||
|
</treerow>
|
||||||
|
</treeitem>
|
||||||
|
</treechildren>
|
||||||
|
</template>
|
||||||
|
</tree>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
const Cc = Components.classes;
|
||||||
|
const Ci = Components.interfaces;
|
||||||
|
|
||||||
|
let XULStore = Cc["@mozilla.org/xul/xulstore;1"].getService(Ci.nsIXULStore);
|
||||||
|
let URI = "chrome://mochitests/content/chrome/toolkit/components/xulstore/tests/chrome/window_persistence.xul";
|
||||||
|
|
||||||
|
function opened()
|
||||||
|
{
|
||||||
|
// If the data in the tree has not been loaded yet, wait a bit and try again.
|
||||||
|
var treeView = document.getElementById("tree").view;
|
||||||
|
if (treeView.rowCount != 6 && treeView.rowCount != 17) {
|
||||||
|
setTimeout(opened, 50);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
runTest(treeView);
|
||||||
|
}
|
||||||
|
|
||||||
|
function runTest(treeView)
|
||||||
|
{
|
||||||
|
var firstRun = window.arguments[0];
|
||||||
|
if (firstRun) {
|
||||||
|
document.getElementById("button1").setAttribute("value", "Pressed");
|
||||||
|
document.getElementById("button2").removeAttribute("value");
|
||||||
|
|
||||||
|
document.getElementById("button2").setAttribute("foo", "bar");
|
||||||
|
document.persist("button2", "foo");
|
||||||
|
is(XULStore.getValue(URI, "button2", "foo"), "bar", "attribute persisted")
|
||||||
|
document.getElementById("button2").removeAttribute("foo");
|
||||||
|
document.persist("button2", "foo");
|
||||||
|
is(XULStore.hasValue(URI, "button2", "foo"), false, "attribute removed")
|
||||||
|
|
||||||
|
is(treeView.rowCount, 6, "tree rows are closed");
|
||||||
|
treeView.toggleOpenState(1);
|
||||||
|
treeView.toggleOpenState(7);
|
||||||
|
|
||||||
|
window.close();
|
||||||
|
window.opener.windowOpened();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
is(document.getElementById("button1").getAttribute("value"), "Pressed",
|
||||||
|
"Attribute set");
|
||||||
|
is(document.getElementById("button2").hasAttribute("value"), true,
|
||||||
|
"Attribute cleared");
|
||||||
|
is(document.getElementById("button2").getAttribute("value"), "",
|
||||||
|
"Attribute cleared");
|
||||||
|
is(document.getElementById("button2").hasAttribute("foo"), false,
|
||||||
|
"Attribute cleared");
|
||||||
|
is(document.getElementById("button2").getAttribute("foo"), "",
|
||||||
|
"Attribute cleared");
|
||||||
|
|
||||||
|
is(treeView.rowCount, 17, "tree rows are open");
|
||||||
|
is(treeView.isContainerOpen(0), false, "first closed row");
|
||||||
|
is(treeView.isContainerOpen(1), true, "first open row");
|
||||||
|
is(treeView.isContainerOpen(7), true, "second open row");
|
||||||
|
|
||||||
|
window.close();
|
||||||
|
window.opener.testDone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function is(l, r, n) { window.opener.wrappedJSObject.SimpleTest.is(l,r,n); }
|
||||||
|
|
||||||
|
]]></script>
|
||||||
|
|
||||||
|
</window>
|
6
toolkit/components/xulstore/tests/moz.build
Normal file
6
toolkit/components/xulstore/tests/moz.build
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
MOCHITEST_CHROME_MANIFESTS += ['chrome/chrome.ini']
|
||||||
|
XPCSHELL_TESTS_MANIFESTS += ['xpcshell/xpcshell.ini']
|
31
toolkit/components/xulstore/tests/xpcshell/localstore.rdf
Normal file
31
toolkit/components/xulstore/tests/xpcshell/localstore.rdf
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<RDF:RDF xmlns:NC="http://home.netscape.com/NC-rdf#"
|
||||||
|
xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||||
|
<RDF:Description RDF:about="chrome://browser/content/browser.xul#sidebar-title"
|
||||||
|
value="" />
|
||||||
|
<RDF:Description RDF:about="about:config#prefCol"
|
||||||
|
ordinal="1"
|
||||||
|
sortDirection="ascending" />
|
||||||
|
<RDF:Description RDF:about="chrome://browser/content/browser.xul#addon-bar"
|
||||||
|
collapsed="true" />
|
||||||
|
<RDF:Description RDF:about="about:config">
|
||||||
|
<NC:persist RDF:resource="about:config#prefCol"/>
|
||||||
|
<NC:persist RDF:resource="about:config#lockCol"/>
|
||||||
|
<NC:persist RDF:resource="about:config#typeCol"/>
|
||||||
|
<NC:persist RDF:resource="about:config#valueCol"/>
|
||||||
|
</RDF:Description>
|
||||||
|
<RDF:Description RDF:about="about:config#lockCol"
|
||||||
|
ordinal="3" />
|
||||||
|
<RDF:Description RDF:about="chrome://browser/content/browser.xul">
|
||||||
|
<NC:persist RDF:resource="chrome://browser/content/browser.xul#main-window"/>
|
||||||
|
<NC:persist RDF:resource="chrome://browser/content/browser.xul#addon-bar"/>
|
||||||
|
<NC:persist RDF:resource="chrome://browser/content/browser.xul#sidebar-box"/>
|
||||||
|
<NC:persist RDF:resource="chrome://browser/content/browser.xul#sidebar-title"/>
|
||||||
|
</RDF:Description>
|
||||||
|
<RDF:Description RDF:about="chrome://browser/content/browser.xul#main-window"
|
||||||
|
width="994"
|
||||||
|
height="768"
|
||||||
|
screenX="4"
|
||||||
|
screenY="22"
|
||||||
|
sizemode="normal" />
|
||||||
|
</RDF:RDF>
|
184
toolkit/components/xulstore/tests/xpcshell/test_XULStore.js
Normal file
184
toolkit/components/xulstore/tests/xpcshell/test_XULStore.js
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/◦
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict"
|
||||||
|
|
||||||
|
const Cc = Components.classes;
|
||||||
|
const Ci = Components.interfaces;
|
||||||
|
const Cu = Components.utils;
|
||||||
|
const Cr = Components.results;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/osfile.jsm")
|
||||||
|
|
||||||
|
let XULStore = null;
|
||||||
|
let browserURI = "chrome://browser/content/browser.xul";
|
||||||
|
let aboutURI = "about:config";
|
||||||
|
|
||||||
|
function run_test() {
|
||||||
|
do_get_profile();
|
||||||
|
run_next_test();
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkValue(uri, id, attr, reference) {
|
||||||
|
let value = XULStore.getValue(uri, id, attr);
|
||||||
|
do_check_true(value === reference);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkValueExists(uri, id, attr, exists) {
|
||||||
|
do_check_eq(XULStore.hasValue(uri, id, attr), exists);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getIDs(uri) {
|
||||||
|
let it = XULStore.getIDsEnumerator(uri);
|
||||||
|
let result = [];
|
||||||
|
|
||||||
|
while (it.hasMore()) {
|
||||||
|
let value = it.getNext();
|
||||||
|
result.push(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.sort();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAttributes(uri, id) {
|
||||||
|
let it = XULStore.getAttributeEnumerator(uri, id);
|
||||||
|
|
||||||
|
let result = [];
|
||||||
|
|
||||||
|
while (it.hasMore()) {
|
||||||
|
let value = it.getNext();
|
||||||
|
result.push(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.sort();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkArrays(a, b) {
|
||||||
|
a.sort();
|
||||||
|
b.sort();
|
||||||
|
do_check_true(a.toString() == b.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkOldStore() {
|
||||||
|
checkArrays(['addon-bar', 'main-window', 'sidebar-title'], getIDs(browserURI));
|
||||||
|
checkArrays(['collapsed'], getAttributes(browserURI, 'addon-bar'));
|
||||||
|
checkArrays(['height', 'screenX', 'screenY', 'sizemode', 'width'],
|
||||||
|
getAttributes(browserURI, 'main-window'));
|
||||||
|
checkArrays(['value'], getAttributes(browserURI, 'sidebar-title'));
|
||||||
|
|
||||||
|
checkValue(browserURI, "addon-bar", "collapsed", "true");
|
||||||
|
checkValue(browserURI, "main-window", "width", "994");
|
||||||
|
checkValue(browserURI, "main-window", "height", "768");
|
||||||
|
checkValue(browserURI, "main-window", "screenX", "4");
|
||||||
|
checkValue(browserURI, "main-window", "screenY", "22");
|
||||||
|
checkValue(browserURI, "main-window", "sizemode", "normal");
|
||||||
|
checkValue(browserURI, "sidebar-title", "value", "");
|
||||||
|
|
||||||
|
checkArrays(['lockCol', 'prefCol'], getIDs(aboutURI));
|
||||||
|
checkArrays(['ordinal'], getAttributes(aboutURI, 'lockCol'));
|
||||||
|
checkArrays(['ordinal', 'sortDirection'], getAttributes(aboutURI, 'prefCol'));
|
||||||
|
|
||||||
|
checkValue(aboutURI, "prefCol", "ordinal", "1");
|
||||||
|
checkValue(aboutURI, "prefCol", "sortDirection", "ascending");
|
||||||
|
checkValue(aboutURI, "lockCol", "ordinal", "3");
|
||||||
|
}
|
||||||
|
|
||||||
|
add_task(function* testImport(){
|
||||||
|
let src = "localstore.rdf";
|
||||||
|
let dst = OS.Path.join(OS.Constants.Path.profileDir, src);
|
||||||
|
|
||||||
|
yield OS.File.copy(src, dst);
|
||||||
|
|
||||||
|
// Importing relies on XULStore not yet being loaded before this point.
|
||||||
|
XULStore = Cc["@mozilla.org/xul/xulstore;1"].getService(Ci.nsIXULStore);
|
||||||
|
checkOldStore();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function* testGetValue() {
|
||||||
|
// Get non-existing property
|
||||||
|
checkValue(browserURI, "side-window", "height", "");
|
||||||
|
|
||||||
|
// Get existing property
|
||||||
|
checkValue(browserURI, "main-window", "width", "994");
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function* testHasValue() {
|
||||||
|
// Check non-existing property
|
||||||
|
checkValueExists(browserURI, "side-window", "height", false);
|
||||||
|
|
||||||
|
// Check existing property
|
||||||
|
checkValueExists(browserURI, "main-window", "width", true);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function* testSetValue() {
|
||||||
|
// Set new attribute
|
||||||
|
checkValue(browserURI, "side-bar", "width", "");
|
||||||
|
XULStore.setValue(browserURI, "side-bar", "width", "1000");
|
||||||
|
checkValue(browserURI, "side-bar", "width", "1000");
|
||||||
|
checkArrays(["addon-bar", "main-window", "side-bar", "sidebar-title"], getIDs(browserURI));
|
||||||
|
checkArrays(["width"], getAttributes(browserURI, 'side-bar'));
|
||||||
|
|
||||||
|
// Modify existing property
|
||||||
|
checkValue(browserURI, "side-bar", "width", "1000");
|
||||||
|
XULStore.setValue(browserURI, "side-bar", "width", "1024");
|
||||||
|
checkValue(browserURI, "side-bar", "width", "1024");
|
||||||
|
checkArrays(["addon-bar", "main-window", "side-bar", "sidebar-title"], getIDs(browserURI));
|
||||||
|
checkArrays(["width"], getAttributes(browserURI, 'side-bar'));
|
||||||
|
|
||||||
|
// Add another attribute
|
||||||
|
checkValue(browserURI, "side-bar", "height", "");
|
||||||
|
XULStore.setValue(browserURI, "side-bar", "height", "1000");
|
||||||
|
checkValue(browserURI, "side-bar", "height", "1000");
|
||||||
|
checkArrays(["addon-bar", "main-window", "side-bar", "sidebar-title"], getIDs(browserURI));
|
||||||
|
checkArrays(["width", "height"], getAttributes(browserURI, 'side-bar'));
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function* testRemoveValue() {
|
||||||
|
// Remove first attribute
|
||||||
|
checkValue(browserURI, "side-bar", "width", "1024");
|
||||||
|
XULStore.removeValue(browserURI, "side-bar", "width");
|
||||||
|
checkValue(browserURI, "side-bar", "width", "");
|
||||||
|
checkValueExists(browserURI, "side-bar", "width", false);
|
||||||
|
checkArrays(["addon-bar", "main-window", "side-bar", "sidebar-title"], getIDs(browserURI));
|
||||||
|
checkArrays(["height"], getAttributes(browserURI, 'side-bar'));
|
||||||
|
|
||||||
|
// Remove second attribute
|
||||||
|
checkValue(browserURI, "side-bar", "height", "1000");
|
||||||
|
XULStore.removeValue(browserURI, "side-bar", "height");
|
||||||
|
checkValue(browserURI, "side-bar", "height", "");
|
||||||
|
checkArrays(["addon-bar", "main-window", "sidebar-title"], getIDs(browserURI));
|
||||||
|
|
||||||
|
// Removing an attribute that doesn't exists shouldn't fail
|
||||||
|
XULStore.removeValue(browserURI, "main-window", "bar");
|
||||||
|
|
||||||
|
// Removing from an id that doesn't exists shouldn't fail
|
||||||
|
XULStore.removeValue(browserURI, "foo", "bar");
|
||||||
|
|
||||||
|
// Removing from a document that doesn't exists shouldn't fail
|
||||||
|
let nonDocURI = "chrome://example/content/other.xul";
|
||||||
|
XULStore.removeValue(nonDocURI, "foo", "bar");
|
||||||
|
|
||||||
|
// Remove all attributes in browserURI
|
||||||
|
XULStore.removeValue(browserURI, "addon-bar", "collapsed");
|
||||||
|
checkArrays([], getAttributes(browserURI, "addon-bar"));
|
||||||
|
XULStore.removeValue(browserURI, "main-window", "width");
|
||||||
|
XULStore.removeValue(browserURI, "main-window", "height");
|
||||||
|
XULStore.removeValue(browserURI, "main-window", "screenX");
|
||||||
|
XULStore.removeValue(browserURI, "main-window", "screenY");
|
||||||
|
XULStore.removeValue(browserURI, "main-window", "sizemode");
|
||||||
|
checkArrays([], getAttributes(browserURI, "main-window"));
|
||||||
|
XULStore.removeValue(browserURI, "sidebar-title", "value");
|
||||||
|
checkArrays([], getAttributes(browserURI, "sidebar-title"));
|
||||||
|
checkArrays([], getIDs(browserURI));
|
||||||
|
|
||||||
|
// Remove all attributes in aboutURI
|
||||||
|
XULStore.removeValue(aboutURI, "prefCol", "ordinal");
|
||||||
|
XULStore.removeValue(aboutURI, "prefCol", "sortDirection");
|
||||||
|
checkArrays([], getAttributes(aboutURI, "prefCol"));
|
||||||
|
XULStore.removeValue(aboutURI, "lockCol", "ordinal");
|
||||||
|
checkArrays([], getAttributes(aboutURI, "lockCol"));
|
||||||
|
checkArrays([], getIDs(aboutURI));
|
||||||
|
});
|
6
toolkit/components/xulstore/tests/xpcshell/xpcshell.ini
Normal file
6
toolkit/components/xulstore/tests/xpcshell/xpcshell.ini
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[DEFAULT]
|
||||||
|
|
||||||
|
support-files =
|
||||||
|
localstore.rdf
|
||||||
|
|
||||||
|
[test_XULStore.js]
|
@ -476,17 +476,8 @@ add_test(function() {
|
|||||||
// Before we open the add-ons manager, we should make sure that no filter
|
// Before we open the add-ons manager, we should make sure that no filter
|
||||||
// has been set. If one is set, we remove it.
|
// has been set. If one is set, we remove it.
|
||||||
// This is for the check below, from bug 611459.
|
// This is for the check below, from bug 611459.
|
||||||
let RDF = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
|
let store = Cc["@mozilla.org/xul/xulstore;1"].getService(Ci.nsIXULStore);
|
||||||
let store = RDF.GetDataSource("rdf:local-store");
|
store.removeValue("about:addons", "search-filter-radiogroup", "value");
|
||||||
let filterResource = RDF.GetResource("about:addons#search-filter-radiogroup");
|
|
||||||
let filterProperty = RDF.GetResource("value");
|
|
||||||
let filterTarget = store.GetTarget(filterResource, filterProperty, true);
|
|
||||||
|
|
||||||
if (filterTarget) {
|
|
||||||
is(filterTarget instanceof Ci.nsIRDFLiteral, true,
|
|
||||||
"Filter should be a value");
|
|
||||||
store.Unassert(filterResource, filterProperty, filterTarget);
|
|
||||||
}
|
|
||||||
|
|
||||||
open_manager("addons://list/extension", function(aManager) {
|
open_manager("addons://list/extension", function(aManager) {
|
||||||
info("Part 1");
|
info("Part 1");
|
||||||
|
Loading…
Reference in New Issue
Block a user