238 lines
8.3 KiB
JavaScript
238 lines
8.3 KiB
JavaScript
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
* The contents of this file are subject to the Mozilla Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1999 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s): Stephen Lamm <slamm@netscape.com>
|
|
*/
|
|
|
|
/*
|
|
* No magic constructor behaviour, as is de rigeur for XPCOM.
|
|
* If you must perform some initialization, and it could possibly fail (even
|
|
* due to an out-of-memory condition), you should use an Init method, which
|
|
* can convey failure appropriately (thrown exception in JS,
|
|
* NS_FAILED(nsresult) return in C++).
|
|
*
|
|
* In JS, you can actually cheat, because a thrown exception will cause the
|
|
* CreateInstance call to fail in turn, but not all languages are so lucky.
|
|
* (Though ANSI C++ provides exceptions, they are verboten in Mozilla code
|
|
* for portability reasons -- and even when you're building completely
|
|
* platform-specific code, you can't throw across an XPCOM method boundary.)
|
|
*/
|
|
|
|
const DEBUG = true; /* set to false to suppress debug messages */
|
|
const PANELS_RDF_FILE = 66626; /* the magic number to find panels.rdf */
|
|
|
|
const SIDEBAR_PROGID = "component://mozilla/sidebar";
|
|
const SIDEBAR_CID = Components.ID("{22117140-9c6e-11d3-aaf1-00805f8a4905}");
|
|
const CONTAINER_PROGID = "component://netscape/rdf/container";
|
|
const LOCATOR_PROGID = "component://netscape/filelocator";
|
|
const nsISupports = Components.interfaces.nsISupports;
|
|
const nsIFactory = Components.interfaces.nsIFactory;
|
|
const nsISidebar = Components.interfaces.nsISidebar;
|
|
const nsIRDFContainer = Components.interfaces.nsIRDFContainer;
|
|
const nsIFileLocator = Components.interfaces.nsIFileLocator;
|
|
const nsIRDFRemoteDataSource = Components.interfaces.nsIRDFRemoteDataSource;
|
|
|
|
function nsSidebar()
|
|
{
|
|
const RDF_PROGID = "component://netscape/rdf/rdf-service";
|
|
const nsIRDFService = Components.interfaces.nsIRDFService;
|
|
|
|
this.rdf = Components.classes[RDF_PROGID].getService(nsIRDFService);
|
|
this.datasource_uri = getSidebarDatasourceURI(PANELS_RDF_FILE);
|
|
debug('datasource_uri is ' + this.datasource_uri);
|
|
this.resource = 'urn:sidebar:current-panel-list';
|
|
this.datasource = this.rdf.GetDataSource(this.datasource_uri);
|
|
}
|
|
|
|
nsSidebar.prototype.nc = "http://home.netscape.com/NC-rdf#";
|
|
|
|
nsSidebar.prototype.setWindow =
|
|
function (aWindow)
|
|
{
|
|
this.window = aWindow;
|
|
}
|
|
|
|
nsSidebar.prototype.isPanel =
|
|
function (aContentURL)
|
|
{
|
|
var container =
|
|
Components.classes[CONTAINER_PROGID].createInstance(nsIRDFContainer);
|
|
|
|
container.Init(this.datasource, this.rdf.GetResource(this.resource));
|
|
|
|
/* Create a resource for the new panel and add it to the list */
|
|
var panel_resource =
|
|
this.rdf.GetResource("urn:sidebar:3rdparty-panel:" + aContentURL);
|
|
|
|
return (container.IndexOf(panel_resource) != -1);
|
|
}
|
|
|
|
|
|
/* decorate prototype to provide ``class'' methods and property accessors */
|
|
nsSidebar.prototype.addPanel =
|
|
function (aTitle, aContentURL, aCustomizeURL)
|
|
{
|
|
debug("addPanel(" + aTitle + ", " + aContentURL + ", " +
|
|
aCustomizeURL + ")");
|
|
|
|
if (!this.window)
|
|
{
|
|
debug ("no window object set, bailing out.");
|
|
throw Components.results.NS_ERROR_NOT_INITIALIZED;
|
|
}
|
|
|
|
/* Create a "container" wrapper around the
|
|
* "urn:sidebar:current-panel-list" object. This makes it easier
|
|
* to manipulate the RDF:Seq correctly. */
|
|
var container =
|
|
Components.classes[CONTAINER_PROGID].createInstance(nsIRDFContainer);
|
|
container.Init(this.datasource, this.rdf.GetResource(this.resource));
|
|
|
|
/* Create a resource for the new panel and add it to the list */
|
|
var panel_resource =
|
|
this.rdf.GetResource("urn:sidebar:3rdparty-panel:" + aContentURL);
|
|
var panel_index = container.IndexOf(panel_resource);
|
|
if (panel_index != -1)
|
|
{
|
|
this.window.alert(aContentURL + " already exists in your sidebar.");
|
|
return;
|
|
}
|
|
|
|
var rv = this.window.confirm("Add " + aContentURL + " to your sidebar?");
|
|
if (!rv)
|
|
return;
|
|
|
|
this.datasource.Assert(this.rdf.GetResource(this.resource),
|
|
this.rdf.GetResource(this.nc + "inbatch"),
|
|
this.rdf.GetLiteral("true"),
|
|
true);
|
|
|
|
/* Now make some sidebar-ish assertions about it... */
|
|
this.datasource.Assert(panel_resource,
|
|
this.rdf.GetResource(this.nc + "title"),
|
|
this.rdf.GetLiteral(aTitle),
|
|
true);
|
|
this.datasource.Assert(panel_resource,
|
|
this.rdf.GetResource(this.nc + "content"),
|
|
this.rdf.GetLiteral(aContentURL),
|
|
true);
|
|
if (aCustomizeURL)
|
|
this.datasource.Assert(panel_resource,
|
|
this.rdf.GetResource(this.nc + "customize"),
|
|
this.rdf.GetLiteral(aCustomizeURL),
|
|
true);
|
|
|
|
container.AppendElement(panel_resource);
|
|
|
|
this.datasource.Unassert(this.rdf.GetResource(this.resource),
|
|
this.rdf.GetResource(this.nc + "inbatch"),
|
|
this.rdf.GetLiteral("true"));
|
|
|
|
/* Write the modified panels out. */
|
|
this.datasource.QueryInterface(nsIRDFRemoteDataSource).Flush();
|
|
|
|
}
|
|
|
|
var sidebarModule = new Object();
|
|
|
|
sidebarModule.registerSelf =
|
|
function (compMgr, fileSpec, location, type)
|
|
{
|
|
debug("registering (all right -- a JavaScript module!)");
|
|
compMgr.registerComponentWithType(SIDEBAR_CID, "Sidebar JS Component",
|
|
SIDEBAR_PROGID, fileSpec, location,
|
|
true, true, type);
|
|
}
|
|
|
|
sidebarModule.getClassObject =
|
|
function (compMgr, cid, iid) {
|
|
if (!cid.equals(SIDEBAR_CID))
|
|
throw Components.results.NS_ERROR_NO_INTERFACE;
|
|
|
|
if (!iid.equals(Components.interfaces.nsIFactory))
|
|
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
return sidebarFactory;
|
|
}
|
|
|
|
sidebarModule.canUnload =
|
|
function(compMgr)
|
|
{
|
|
debug("Unloading component.");
|
|
return true;
|
|
}
|
|
|
|
/* factory object */
|
|
sidebarFactory = new Object();
|
|
|
|
sidebarFactory.CreateInstance =
|
|
function (outer, iid) {
|
|
debug("CI: " + iid);
|
|
if (outer != null)
|
|
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
|
|
|
if (!iid.equals(nsISidebar) && !iid.equals(nsISupports))
|
|
throw Components.results.NS_ERROR_INVALID_ARG;
|
|
|
|
return new nsSidebar();
|
|
}
|
|
|
|
/* entrypoint */
|
|
function NSGetModule(compMgr, fileSpec) {
|
|
return sidebarModule;
|
|
}
|
|
|
|
/* static functions */
|
|
if (DEBUG)
|
|
debug = function (s) { dump("-*- sidebar: " + s + "\n"); }
|
|
else
|
|
debug = function (s) {}
|
|
|
|
function getSidebarDatasourceURI(panels_file_id)
|
|
{
|
|
try
|
|
{
|
|
/* use the fileLocator to look in the profile directory
|
|
* to find 'panels.rdf', which is the
|
|
* database of the user's currently selected panels. */
|
|
var fileLocatorService =
|
|
Components.classes[LOCATOR_PROGID].getService(nsIFileLocator);
|
|
|
|
/* if <profile>/panels.rdf doesn't exist, GetFileLocation() will copy
|
|
*bin/defaults/profile/panels.rdf to <profile>/panels.rdf */
|
|
var sidebar_file = fileLocatorService.GetFileLocation(panels_file_id);
|
|
|
|
if (!sidebar_file.exists())
|
|
{
|
|
/* this should not happen, as GetFileLocation() should copy
|
|
* defaults/panels.rdf to the users profile directory */
|
|
debug("sidebar file does not exist");
|
|
return null;
|
|
}
|
|
|
|
debug("sidebar uri is " + sidebar_file.URLString);
|
|
return sidebar_file.URLString;
|
|
}
|
|
catch (ex)
|
|
{
|
|
/* this should not happen */
|
|
debug("caught " + ex + " getting sidebar datasource uri");
|
|
return null;
|
|
}
|
|
}
|