home *** CD-ROM | disk | FTP | other *** search
/ PC World 2000 December / PCWorld_2000-12_cd.bin / Komunikace / mozilla / mozilla-win32-M18-mathml-svg-xslt.exe / components / nsSidebar.js < prev    next >
Text File  |  2000-09-14  |  17KB  |  432 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is mozilla.org code.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are
  16.  * Copyright (C) 1999 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s): Stephen Lamm            <slamm@netscape.com>
  20.  *                 Robert John Churchill   <rjc@netscape.com>
  21.  */
  22.  
  23. /*
  24.  * No magic constructor behaviour, as is de rigeur for XPCOM.
  25.  * If you must perform some initialization, and it could possibly fail (even
  26.  * due to an out-of-memory condition), you should use an Init method, which
  27.  * can convey failure appropriately (thrown exception in JS,
  28.  * NS_FAILED(nsresult) return in C++).
  29.  *
  30.  * In JS, you can actually cheat, because a thrown exception will cause the
  31.  * CreateInstance call to fail in turn, but not all languages are so lucky.
  32.  * (Though ANSI C++ provides exceptions, they are verboten in Mozilla code
  33.  * for portability reasons -- and even when you're building completely
  34.  * platform-specific code, you can't throw across an XPCOM method boundary.)
  35.  */
  36.  
  37. const DEBUG = false; /* set to false to suppress debug messages */
  38. const PANELS_RDF_FILE  = "UPnls"; /* directory services property to find panels.rdf */
  39.  
  40. const SIDEBAR_CONTRACTID   = "@mozilla.org/sidebar;1";
  41. const SIDEBAR_CID      = Components.ID("{22117140-9c6e-11d3-aaf1-00805f8a4905}");
  42. const CONTAINER_CONTRACTID = "@mozilla.org/rdf/container;1";
  43. const DIR_SERV_CONTRACTID  = "@mozilla.org/file/directory_service;1"
  44. const STD_URL_CONTRACTID   = "@mozilla.org/network/standard-url;1"
  45. const NETSEARCH_CONTRACTID = "@mozilla.org/rdf/datasource;1?name=internetsearch"
  46. const nsISupports      = Components.interfaces.nsISupports;
  47. const nsIFactory       = Components.interfaces.nsIFactory;
  48. const nsISidebar       = Components.interfaces.nsISidebar;
  49. const nsIRDFContainer  = Components.interfaces.nsIRDFContainer;
  50. const nsIProperties    = Components.interfaces.nsIProperties;
  51. const nsIFileURL       = Components.interfaces.nsIFileURL;
  52. const nsIRDFRemoteDataSource = Components.interfaces.nsIRDFRemoteDataSource;
  53. const nsIInternetSearchService = Components.interfaces.nsIInternetSearchService;
  54. const nsISecurityCheckedComponent = Components.interfaces.nsISecurityCheckedComponent;
  55.  
  56. function nsSidebar()
  57. {
  58.     const RDF_CONTRACTID = "@mozilla.org/rdf/rdf-service;1";
  59.     const nsIRDFService = Components.interfaces.nsIRDFService;
  60.     
  61.     this.rdf = Components.classes[RDF_CONTRACTID].getService(nsIRDFService);
  62.     this.datasource_uri = getSidebarDatasourceURI(PANELS_RDF_FILE);
  63.     debug('datasource_uri is ' + this.datasource_uri);
  64.     this.resource = 'urn:sidebar:current-panel-list';
  65.     this.datasource = this.rdf.GetDataSource(this.datasource_uri);
  66. }
  67.  
  68. nsSidebar.prototype.nc = "http://home.netscape.com/NC-rdf#";
  69.  
  70. nsSidebar.prototype.setWindow =
  71. function (aWindow)
  72. {    
  73.     this.window = aWindow;    
  74. }
  75.  
  76. nsSidebar.prototype.isPanel =
  77. function (aContentURL)
  78. {
  79.     var container = 
  80.         Components.classes[CONTAINER_CONTRACTID].createInstance(nsIRDFContainer);
  81.  
  82.     container.Init(this.datasource, this.rdf.GetResource(this.resource));
  83.     
  84.     /* Create a resource for the new panel and add it to the list */
  85.     var panel_resource = 
  86.         this.rdf.GetResource("urn:sidebar:3rdparty-panel:" + aContentURL);
  87.  
  88.     return (container.IndexOf(panel_resource) != -1);
  89. }
  90.  
  91.  
  92. /* decorate prototype to provide ``class'' methods and property accessors */
  93. nsSidebar.prototype.addPanel =
  94. function (aTitle, aContentURL, aCustomizeURL)
  95. {
  96.     debug("addPanel(" + aTitle + ", " + aContentURL + ", " +
  97.           aCustomizeURL + ")");
  98.  
  99.     if (!this.window)
  100.     {
  101.         debug ("no window object set, bailing out.");
  102.         throw Components.results.NS_ERROR_NOT_INITIALIZED;
  103.     }
  104.  
  105.     // Create a "container" wrapper around the current panels to
  106.     // manipulate the RDF:Seq more easily.
  107.     var panel_list = this.datasource.GetTarget(this.rdf.GetResource(this.resource), this.rdf.GetResource(nsSidebar.prototype.nc+"panel-list"), true);
  108.     if (panel_list) {
  109.         panel_list.QueryInterface(Components.interfaces.nsIRDFResource);
  110.     } else {
  111.         // Datasource is busted. Start over.
  112.         debug("Sidebar datasource is busted\n");
  113.   }
  114.  
  115.     var container = Components.classes[CONTAINER_CONTRACTID].createInstance(nsIRDFContainer);
  116.     container.Init(this.datasource, panel_list);
  117.  
  118.     /* Create a resource for the new panel and add it to the list */
  119.     var panel_resource = 
  120.         this.rdf.GetResource("urn:sidebar:3rdparty-panel:" + aContentURL);
  121.     var panel_index = container.IndexOf(panel_resource);
  122.     if (panel_index != -1)
  123.     {
  124.         var titleMessage, dialogMessage;
  125.         try {
  126.             var stringBundle = getStringBundle("chrome://communicator/locale/sidebar/sidebar.properties");
  127.             if (stringBundle) {
  128.                 titleMessage = stringBundle.GetStringFromName("dupePanelAlertTitle");
  129.                 dialogMessage = stringBundle.GetStringFromName("dupePanelAlertMessage");
  130.                 dialogMessage = dialogMessage.replace(/%url%/, aContentURL);
  131.             }
  132.         }
  133.         catch (e) {
  134.             titleMessage = "My Sidebar";
  135.             dialogMessage = aContentURL + " already exists in My Sidebar.";
  136.         }
  137.           
  138.         var cDlgService = Components.classes["@mozilla.org/appshell/commonDialogs;1"].getService();
  139.         if (cDlgService) 
  140.             cDlgService = cDlgService.QueryInterface(Components.interfaces.nsICommonDialogs);
  141.         cDlgService.Alert(this.window, titleMessage, dialogMessage);
  142.  
  143.         return;
  144.     }
  145.     
  146.     var titleMessage, dialogMessage;
  147.     try {
  148.         var stringBundle = getStringBundle("chrome://communicator/locale/sidebar/sidebar.properties");
  149.         if (stringBundle) {
  150.             titleMessage = stringBundle.GetStringFromName("addPanelConfirmTitle");
  151.             dialogMessage = stringBundle.GetStringFromName("addPanelConfirmMessage");
  152.             dialogMessage = dialogMessage.replace(/%title%/, aTitle);
  153.             dialogMessage = dialogMessage.replace(/%url%/, aContentURL);
  154.             dialogMessage = dialogMessage.replace(/#/g, "\n");
  155.         }
  156.     }
  157.     catch (e) {
  158.         titleMessage = "Add Tab to My Sidebar";
  159.         dialogMessage = "Add the Tab '" + aTitle + "' to My Sidebar?\n\n" + "Source: " + aContentURL;
  160.     }
  161.           
  162.     var cDlgService = Components.classes["@mozilla.org/appshell/commonDialogs;1"].getService();
  163.     if (cDlgService) 
  164.         cDlgService = cDlgService.QueryInterface(Components.interfaces.nsICommonDialogs);
  165.     var rv = cDlgService.Confirm(this.window, titleMessage, dialogMessage);
  166.       
  167.     if (!rv)
  168.         return;
  169.  
  170.     /* Now make some sidebar-ish assertions about it... */
  171.     this.datasource.Assert(panel_resource,
  172.                            this.rdf.GetResource(this.nc + "title"),
  173.                            this.rdf.GetLiteral(aTitle),
  174.                            true);
  175.     this.datasource.Assert(panel_resource,
  176.                            this.rdf.GetResource(this.nc + "content"),
  177.                            this.rdf.GetLiteral(aContentURL),
  178.                            true);
  179.     if (aCustomizeURL)
  180.         this.datasource.Assert(panel_resource,
  181.                                this.rdf.GetResource(this.nc + "customize"),
  182.                                this.rdf.GetLiteral(aCustomizeURL),
  183.                                true);
  184.         
  185.     container.AppendElement(panel_resource);
  186.  
  187.     // Use an assertion to pass a "refresh" event to all the sidebars.
  188.     // They use observers to watch for this assertion (in sidebarOverlay.js).
  189.     this.datasource.Assert(this.rdf.GetResource(this.resource),
  190.                            this.rdf.GetResource(this.nc + "refresh"),
  191.                            this.rdf.GetLiteral("true"),
  192.                            true);
  193.     this.datasource.Unassert(this.rdf.GetResource(this.resource),
  194.                              this.rdf.GetResource(this.nc + "refresh"),
  195.                              this.rdf.GetLiteral("true"));
  196.  
  197.     /* Write the modified panels out. */
  198.     this.datasource.QueryInterface(nsIRDFRemoteDataSource).Flush();
  199.  
  200. }
  201.  
  202. /* decorate prototype to provide ``class'' methods and property accessors */
  203. nsSidebar.prototype.addSearchEngine =
  204. function (engineURL, iconURL, suggestedTitle, suggestedCategory)
  205. {
  206.     debug("addSearchEngine(" + engineURL + ", " + iconURL + ", " +
  207.           suggestedCategory + ", " + suggestedTitle + ")");
  208.  
  209.     if (!this.window)
  210.     {
  211.         debug ("no window object set, bailing out.");
  212.         throw Components.results.NS_ERROR_NOT_INITIALIZED;
  213.     }
  214.  
  215.     try
  216.     {
  217.         // make sure using HTTP (for both engine as well as icon URLs)
  218.  
  219.         if (engineURL.search(/^http:\/\//i) == -1)
  220.         {
  221.             debug ("must use HTTP to fetch search engine file");
  222.             throw Components.results.NS_ERROR_INVALID_ARG;
  223.         }
  224.  
  225.         if (iconURL.search(/^http:\/\//i) == -1)
  226.         {
  227.             debug ("must use HTTP to fetch search icon file");
  228.             throw Components.results.NS_ERROR_INVALID_ARG;
  229.         }
  230.  
  231.         // make sure engineURL refers to a .src file
  232.         if (engineURL.search(/\.src$/i) == -1)
  233.         {
  234.             debug ("engineURL doesn't reference a .src file");
  235.             throw Components.results.NS_ERROR_INVALID_ARG;
  236.         }
  237.  
  238.         // make sure iconURL refers to a .gif/.jpg/.jpeg/.png file
  239.         if (iconURL.search(/\.(gif|jpg|jpeg|png)$/i) == -1)
  240.         {
  241.             debug ("iconURL doesn't reference a supported image file");
  242.             throw Components.results.NS_ERROR_INVALID_ARG;
  243.         }
  244.  
  245.     }
  246.     catch(ex)
  247.     {
  248.         this.window.alert("Failed to add the search engine.\n");
  249.         throw Components.results.NS_ERROR_INVALID_ARG;
  250.     }
  251.  
  252.     var titleMessage, dialogMessage;
  253.     try {
  254.         var stringBundle = getStringBundle("chrome://communicator/locale/sidebar/sidebar.properties");
  255.         if (stringBundle) {
  256.             titleMessage = stringBundle.GetStringFromName("addEngineConfirmTitle");
  257.             dialogMessage = stringBundle.GetStringFromName("addEngineConfirmMessage");
  258.             dialogMessage = dialogMessage.replace(/%title%/, suggestedTitle);
  259.             dialogMessage = dialogMessage.replace(/%category%/, suggestedCategory);
  260.             dialogMessage = dialogMessage.replace(/%url%/, engineURL);
  261.             dialogMessage = dialogMessage.replace(/#/g, "\n");
  262.         }
  263.     }
  264.     catch (e) {
  265.         titleMessage = "Add Search Engine";
  266.         dialogMessage = "Add the following search engine?\n\nName: " + suggestedTitle;
  267.         dialogMessage += "\nSearch Category: " + suggestedCategory;
  268.         dialogMessage += "\nSource: " + engineURL;
  269.     }
  270.           
  271.     var cDlgService = Components.classes["@mozilla.org/appshell/commonDialogs;1"].getService();
  272.     if (cDlgService) 
  273.         cDlgService = cDlgService.QueryInterface(Components.interfaces.nsICommonDialogs);
  274.     var rv = cDlgService.Confirm(this.window, titleMessage, dialogMessage);
  275.       
  276.     if (!rv)
  277.         return;
  278.  
  279.     var internetSearch = Components.classes[NETSEARCH_CONTRACTID].getService();
  280.     if (internetSearch)    
  281.         internetSearch = internetSearch.QueryInterface(nsIInternetSearchService);
  282.     if (internetSearch)
  283.     {
  284.         internetSearch.AddSearchEngine(engineURL, iconURL, suggestedTitle,
  285.                                        suggestedCategory);
  286.     }
  287. }
  288.  
  289. // method of nsISecurityCheckedComponent
  290. nsSidebar.prototype.canCreateWrapper =
  291. function (iid) {
  292.     return "NoAccess";
  293. }
  294.  
  295. // method of nsISecurityCheckedComponent
  296. nsSidebar.prototype.canCallMethod =
  297. function (iid, methodName) {
  298.     if (iid.equals(nsISidebar) &&
  299.         (methodName == "setWindow" ||
  300.          methodName == "addPanel" ||
  301.          methodName == "addSearchEngine")) {
  302.         return "AllAccess";
  303.     } else {
  304.         return "NoAccess";
  305.     }
  306. }
  307.  
  308. // method of nsISecurityCheckedComponent
  309. nsSidebar.prototype.canGetProperty =
  310. function (iid, propertyName) {
  311.     return "NoAccess";
  312. }
  313.  
  314. // method of nsISecurityCheckedComponent
  315. nsSidebar.prototype.canSetProperty =
  316. function (iid, propertyName) {
  317.     return "NoAccess";
  318. }
  319.  
  320. nsSidebar.prototype.QueryInterface =
  321. function (iid) {
  322.     if (!iid.equals(nsISidebar) && 
  323.         !iid.equals(nsISecurityCheckedComponent) &&
  324.         !iid.equals(nsISupports))
  325.         throw Components.results.NS_ERROR_NO_INTERFACE;
  326.     return this;
  327. }
  328.  
  329. var sidebarModule = new Object();
  330.  
  331. sidebarModule.registerSelf =
  332. function (compMgr, fileSpec, location, type)
  333. {
  334.     debug("registering (all right -- a JavaScript module!)");
  335.     compMgr.registerComponentWithType(SIDEBAR_CID, "Sidebar JS Component",
  336.                                       SIDEBAR_CONTRACTID, fileSpec, location,
  337.                                       true, true, type);
  338. }
  339.  
  340. sidebarModule.getClassObject =
  341. function (compMgr, cid, iid) {
  342.     if (!cid.equals(SIDEBAR_CID))
  343.         throw Components.results.NS_ERROR_NO_INTERFACE;
  344.     
  345.     if (!iid.equals(Components.interfaces.nsIFactory))
  346.         throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  347.     
  348.     return sidebarFactory;
  349. }
  350.  
  351. sidebarModule.canUnload =
  352. function(compMgr)
  353. {
  354.     debug("Unloading component.");
  355.     return true;
  356. }
  357.     
  358. /* factory object */
  359. sidebarFactory = new Object();
  360.  
  361. sidebarFactory.createInstance =
  362. function (outer, iid) {
  363.     debug("CI: " + iid);
  364.     if (outer != null)
  365.         throw Components.results.NS_ERROR_NO_AGGREGATION;
  366.  
  367.     return (new nsSidebar()).QueryInterface(iid);
  368. }
  369.  
  370. /* entrypoint */
  371. function NSGetModule(compMgr, fileSpec) {
  372.     return sidebarModule;
  373. }
  374.  
  375. /* static functions */
  376. if (DEBUG)
  377.     debug = function (s) { dump("-*- sidebar component: " + s + "\n"); }
  378. else
  379.     debug = function (s) {}
  380.  
  381. function getSidebarDatasourceURI(panels_file_id)
  382. {
  383.     try 
  384.     {
  385.         /* use the fileLocator to look in the profile directory 
  386.          * to find 'panels.rdf', which is the
  387.          * database of the user's currently selected panels. */
  388.         var directory_service = Components.classes[DIR_SERV_CONTRACTID].getService();
  389.         if (directory_service)
  390.             directory_service = directory_service.QueryInterface(Components.interfaces.nsIProperties);
  391.  
  392.         /* if <profile>/panels.rdf doesn't exist, get will copy
  393.          *bin/defaults/profile/panels.rdf to <profile>/panels.rdf */
  394.         var sidebar_file = directory_service.get(panels_file_id, Components.interfaces.nsIFile);
  395.  
  396.         if (!sidebar_file.exists())
  397.         {
  398.             /* this should not happen, as GetFileLocation() should copy
  399.              * defaults/panels.rdf to the users profile directory */
  400.             debug("sidebar file does not exist");
  401.             return null;
  402.         }
  403.  
  404.         var file_url = Components.classes[STD_URL_CONTRACTID].createInstance(Components.interfaces.nsIFileURL);
  405.         file_url.file = sidebar_file;
  406.  
  407.         debug("sidebar uri is " + file_url.spec);
  408.         return file_url.spec;
  409.     }
  410.     catch (ex)
  411.     {
  412.         /* this should not happen */
  413.         debug("caught " + ex + " getting sidebar datasource uri");
  414.         return null;
  415.     }
  416. }
  417.  
  418. function getStringBundle(aURL) 
  419. {
  420.   var stringBundleService = Components.classes["@mozilla.org/intl/stringbundle;1"].getService();
  421.   stringBundleService = stringBundleService.QueryInterface(Components.interfaces.nsIStringBundleService);
  422.   var appLocale;
  423.   var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"].getService();
  424.   if (localeService)
  425.     localeService = localeService.QueryInterface(Components.interfaces.nsILocaleService);
  426.   if (localeService)
  427.     appLocale = localeService.GetApplicationLocale();
  428.   var stringBundle = stringBundleService.CreateBundle(aURL, appLocale);
  429.   if (stringBundle)
  430.     return stringBundle.QueryInterface(Components.interfaces.nsIStringBundle);
  431. }
  432.