home *** CD-ROM | disk | FTP | other *** search
/ PC World 2005 December / PCWorld_2005-12_cd.bin / komunikace / netscape / nsb-install-8-0.exe / components / nsSidebar.js < prev    next >
Text File  |  2005-09-26  |  19KB  |  470 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.  *                 David Hyatt             <hyatt@mozilla.org>
  22.  *                 Christopher A. Aillon   <christopher@aillon.com>
  23.  */
  24.  
  25. /*
  26.  * No magic constructor behaviour, as is de rigeur for XPCOM.
  27.  * If you must perform some initialization, and it could possibly fail (even
  28.  * due to an out-of-memory condition), you should use an Init method, which
  29.  * can convey failure appropriately (thrown exception in JS,
  30.  * NS_FAILED(nsresult) return in C++).
  31.  *
  32.  * In JS, you can actually cheat, because a thrown exception will cause the
  33.  * CreateInstance call to fail in turn, but not all languages are so lucky.
  34.  * (Though ANSI C++ provides exceptions, they are verboten in Mozilla code
  35.  * for portability reasons -- and even when you're building completely
  36.  * platform-specific code, you can't throw across an XPCOM method boundary.)
  37.  */
  38.  
  39. const DEBUG = false; /* set to false to suppress debug messages */
  40. const PANELS_RDF_FILE  = "UPnls"; /* directory services property to find panels.rdf */
  41.  
  42. const SIDEBAR_CONTRACTID        = "@mozilla.org/sidebar;1";
  43. const SIDEBAR_CID               = Components.ID("{22117140-9c6e-11d3-aaf1-00805f8a4905}");
  44. const CONTAINER_CONTRACTID = "@mozilla.org/rdf/container;1";
  45. const DIR_SERV_CONTRACTID  = "@mozilla.org/file/directory_service;1"
  46. const NETSEARCH_CONTRACTID      = "@mozilla.org/rdf/datasource;1?name=internetsearch"
  47. const IO_SERV_CONTRACTID   = "@mozilla.org/network/io-service;1";
  48. const nsISupports               = Components.interfaces.nsISupports;
  49. const nsIFactory                = Components.interfaces.nsIFactory;
  50. const nsISidebar                = Components.interfaces.nsISidebar;
  51. const nsIRDFContainer  = Components.interfaces.nsIRDFContainer;
  52. const nsIProperties    = Components.interfaces.nsIProperties;
  53. const nsIFileURL       = Components.interfaces.nsIFileURL;
  54. const nsIRDFRemoteDataSource = Components.interfaces.nsIRDFRemoteDataSource;
  55. const nsIInternetSearchService  = Components.interfaces.nsIInternetSearchService;
  56. const nsIClassInfo              = Components.interfaces.nsIClassInfo;
  57.  
  58. function nsSidebar()
  59. {
  60.     const RDF_CONTRACTID = "@mozilla.org/rdf/rdf-service;1";
  61.     const nsIRDFService = Components.interfaces.nsIRDFService;
  62.     this.rdf = Components.classes[RDF_CONTRACTID].getService(nsIRDFService);
  63.     this.datasource_uri = getSidebarDatasourceURI(PANELS_RDF_FILE);
  64.     debug('datasource_uri is ' + this.datasource_uri);
  65.     this.resource = 'urn:sidebar:current-panel-list';
  66.     this.datasource = this.rdf.GetDataSource(this.datasource_uri);
  67.     const PROMPTSERVICE_CONTRACTID = "@mozilla.org/embedcomp/prompt-service;1";
  68.     const nsIPromptService = Components.interfaces.nsIPromptService;
  69.     this.promptService =
  70.         Components.classes[PROMPTSERVICE_CONTRACTID].getService(nsIPromptService);
  71. }
  72.  
  73. nsSidebar.prototype.nc = "http://home.netscape.com/NC-rdf#";
  74.  
  75. nsSidebar.prototype.isPanel =
  76. function (aContentURL)
  77. {
  78.     var container = 
  79.         Components.classes[CONTAINER_CONTRACTID].createInstance(nsIRDFContainer);
  80.  
  81.     container.Init(this.datasource, this.rdf.GetResource(this.resource));
  82.     
  83.     /* Create a resource for the new panel and add it to the list */
  84.     var panel_resource = 
  85.         this.rdf.GetResource("urn:sidebar:3rdparty-panel:" + aContentURL);
  86.  
  87.     return (container.IndexOf(panel_resource) != -1);
  88. }
  89.  
  90. function sidebarURLSecurityCheck(url)
  91. {
  92.     if (url.search(/(^http:|^ftp:|^https:)/) == -1)
  93.         throw "Script attempted to add sidebar panel from illegal source";
  94. }
  95.  
  96. /* decorate prototype to provide ``class'' methods and property accessors */
  97. nsSidebar.prototype.addPanel =
  98. function (aTitle, aContentURL, aCustomizeURL)
  99. {
  100.     debug("addPanel(" + aTitle + ", " + aContentURL + ", " +
  101.           aCustomizeURL + ")");
  102.    
  103.     return this.addPanelInternal(aTitle, aContentURL, aCustomizeURL, false);
  104. }
  105.  
  106. nsSidebar.prototype.addPersistentPanel = 
  107. function(aTitle, aContentURL, aCustomizeURL)
  108. {
  109.     debug("addPersistentPanel(" + aTitle + ", " + aContentURL + ", " +
  110.            aCustomizeURL + ")\n");
  111.  
  112.     return this.addPanelInternal(aTitle, aContentURL, aCustomizeURL, true);
  113. }
  114.  
  115. /*nsSidebar.prototype.addPanelInternal2 =
  116. function (aTitle, aContentURL, aCustomizeURL, aPersist)
  117. {
  118.     var WINMEDSVC = Components.classes['@mozilla.org/appshell/window-mediator;1']
  119.                               .getService(Components.interfaces.nsIWindowMediator);
  120.     var win = WINMEDSVC.getMostRecentWindow( "navigator:browser" );
  121.                                                                                 
  122.     sidebarURLSecurityCheck(aContentURL);
  123.     win.openDialog("chrome://browser/content/bookmarks/addBookmark2.xul", "",
  124.                    "centerscreen,chrome,dialog,resizable,dependent",
  125.                    aTitle, aContentURL, null, null, null, null, true);
  126. }*/
  127.  
  128. nsSidebar.prototype.addPanelInternal =
  129. function (aTitle, aContentURL, aCustomizeURL, aPersist)
  130. {
  131.     sidebarURLSecurityCheck(aContentURL);
  132.  
  133.     // Create a "container" wrapper around the current panels to
  134.     // manipulate the RDF:Seq more easily.
  135.     var panel_list = this.datasource.GetTarget(this.rdf.GetResource(this.resource), this.rdf.GetResource(nsSidebar.prototype.nc+"panel-list"), true);
  136.     if (panel_list) {
  137.         panel_list.QueryInterface(Components.interfaces.nsIRDFResource);
  138.     } else {
  139.         // Datasource is busted. Start over.
  140.         debug("Sidebar datasource is busted\n");
  141.     }
  142.  
  143.     var container = Components.classes[CONTAINER_CONTRACTID].createInstance(nsIRDFContainer);
  144.     container.Init(this.datasource, panel_list);
  145.  
  146.     /* Create a resource for the new panel and add it to the list */
  147.     var panel_resource = 
  148.         this.rdf.GetResource("urn:sidebar:3rdparty-panel:" + aContentURL);
  149.     var panel_index = container.IndexOf(panel_resource);
  150.     var stringBundle, brandStringBundle, titleMessage, dialogMessage;
  151.     if (panel_index != -1)
  152.     {
  153.         try {
  154.             stringBundle = srGetStrBundle("chrome://browser/locale/sidebar/sidebar.properties");
  155.             //brandStringBundle = srGetStrBundle("chrome://global/locale/brand.properties");
  156.             if (stringBundle) {
  157.                 //sidebarName = brandStringBundle.GetStringFromName("sidebarName");
  158.                 sidebarName = "Sidebar";
  159.                 titleMessage = stringBundle.GetStringFromName("dupePanelAlertTitle");
  160.                 dialogMessage = stringBundle.GetStringFromName("dupePanelAlertMessage");
  161.                 dialogMessage = dialogMessage.replace(/%url%/, aContentURL);
  162.                 dialogMessage = dialogMessage.replace(/%name%/, sidebarName);
  163.             }
  164.         }
  165.         catch (e) {
  166.             titleMessage = "Sidebar";
  167.             dialogMessage = aContentURL + " already exists in Sidebar.  No string bundle";
  168.         }
  169.           
  170.         this.promptService.alert(null, titleMessage, dialogMessage);
  171.  
  172.         return;
  173.     }
  174.  
  175.     try {
  176.         stringBundle = srGetStrBundle("chrome://browser/locale/sidebar/sidebar.properties");
  177.         //brandStringBundle = srGetStrBundle("chrome://global/locale/brand.properties");
  178.         if (stringBundle) {                        
  179.             titleMessage = stringBundle.GetStringFromName("addPanelConfirmTitle");                                    
  180.             dialogMessage = stringBundle.GetStringFromName("addPanelConfirmMessage");                                    
  181.             if (aPersist)
  182.             {
  183.                 var warning = stringBundle.GetStringFromName("persistentPanelWarning");
  184.                 dialogMessage += "\n" + warning;
  185.             }
  186.             dialogMessage = dialogMessage.replace(/%title%/, aTitle);
  187.             dialogMessage = dialogMessage.replace(/%url%/, aContentURL);
  188.             dialogMessage = dialogMessage.replace(/#/g, "\n");
  189.             dialogMessage = dialogMessage.replace(/%name%/g, sidebarName);
  190.         }
  191.     }
  192.     catch (e) {
  193.         titleMessage = "Add Tab to Sidebar";        
  194.     dialogMessage = "Add the Tab '" + aTitle + "' to Sidebar?\n\n" + "Source: " + aContentURL;
  195.  
  196.     }
  197.           
  198.     var rv = this.promptService.confirm(null, titleMessage, dialogMessage);
  199.       
  200.     if (!rv)
  201.         return;
  202.  
  203.     /* Now make some sidebar-ish assertions about it... */
  204.     this.datasource.Assert(panel_resource,
  205.                            this.rdf.GetResource(this.nc + "title"),
  206.                            this.rdf.GetLiteral(aTitle),
  207.                            true);
  208.     this.datasource.Assert(panel_resource,
  209.                            this.rdf.GetResource(this.nc + "content"),
  210.                            this.rdf.GetLiteral(aContentURL),
  211.                            true);
  212.     if (aCustomizeURL)
  213.         this.datasource.Assert(panel_resource,
  214.                                this.rdf.GetResource(this.nc + "customize"),
  215.                                this.rdf.GetLiteral(aCustomizeURL),
  216.                                true);
  217.     var persistValue = aPersist ? "true" : "false";
  218.     this.datasource.Assert(panel_resource,
  219.                            this.rdf.GetResource(this.nc + "persist"),
  220.                            this.rdf.GetLiteral(persistValue),
  221.                            true);
  222.         
  223.     container.AppendElement(panel_resource);
  224.  
  225.     // Use an assertion to pass a "refresh" event to all the sidebars.
  226.     // They use observers to watch for this assertion (in sidebarOverlay.js).
  227.     this.datasource.Assert(this.rdf.GetResource(this.resource),
  228.                            this.rdf.GetResource(this.nc + "refresh"),
  229.                            this.rdf.GetLiteral("true"),
  230.                            true);
  231.     this.datasource.Unassert(this.rdf.GetResource(this.resource),
  232.                              this.rdf.GetResource(this.nc + "refresh"),
  233.                              this.rdf.GetLiteral("true"));
  234.  
  235.     /* Write the modified panels out. */
  236.     this.datasource.QueryInterface(nsIRDFRemoteDataSource).Flush();
  237.  
  238. }
  239.  
  240. /* decorate prototype to provide ``class'' methods and property accessors */
  241. nsSidebar.prototype.addSearchEngine =
  242. function (engineURL, iconURL, suggestedTitle, suggestedCategory)
  243. {
  244.     debug("addSearchEngine(" + engineURL + ", " + iconURL + ", " +
  245.           suggestedCategory + ", " + suggestedTitle + ")");
  246.  
  247.     try
  248.     {
  249.         // make sure using HTTP (for both engine as well as icon URLs)
  250.  
  251.         if (engineURL.search(/^http:\/\//i) == -1)
  252.         {
  253.             debug ("must use HTTP to fetch search engine file");
  254.             throw Components.results.NS_ERROR_INVALID_ARG;
  255.         }
  256.  
  257.         if (iconURL.search(/^http:\/\//i) == -1)
  258.         {
  259.             debug ("must use HTTP to fetch search icon file");
  260.             throw Components.results.NS_ERROR_INVALID_ARG;
  261.         }
  262.  
  263.         // make sure engineURL refers to a .src file
  264.         if (engineURL.search(/\.src$/i) == -1)
  265.         {
  266.             debug ("engineURL doesn't reference a .src file");
  267.             throw Components.results.NS_ERROR_INVALID_ARG;
  268.         }
  269.  
  270.         // make sure iconURL refers to a .gif/.jpg/.jpeg/.png file
  271.         if (iconURL.search(/\.(gif|jpg|jpeg|png)$/i) == -1)
  272.         {
  273.             debug ("iconURL doesn't reference a supported image file");
  274.             throw Components.results.NS_ERROR_INVALID_ARG;
  275.         }
  276.  
  277.     }
  278.     catch(ex)
  279.     {
  280.         this.promptService.alert(null, "Failed to add the search engine.");
  281.         throw Components.results.NS_ERROR_INVALID_ARG;
  282.     }
  283.  
  284.     var titleMessage, dialogMessage;
  285.     try {
  286.         var stringBundle = srGetStrBundle("chrome://browser/locale/sidebar/sidebar.properties");
  287.         //var brandStringBundle = srGetStrBundle("chrome://global/locale/brand.properties");
  288.         if (stringBundle) {
  289.             //sidebarName = brandStringBundle.GetStringFromName("sidebarName");    
  290.             sidebarName = "Sidebar";        
  291.             titleMessage = stringBundle.GetStringFromName("addEngineConfirmTitle");
  292.             dialogMessage = stringBundle.GetStringFromName("addEngineConfirmMessage");
  293.             dialogMessage = dialogMessage.replace(/%title%/, suggestedTitle);
  294.             dialogMessage = dialogMessage.replace(/%category%/, suggestedCategory);
  295.             dialogMessage = dialogMessage.replace(/%url%/, engineURL);
  296.             dialogMessage = dialogMessage.replace(/#/g, "\n");
  297.             dialogMessage = dialogMessage.replace(/%name%/, sidebarName);
  298.         }
  299.     }
  300.     catch (e) {
  301.         titleMessage = "Add Search Engine";
  302.         dialogMessage = "Add the following search engine?\n\nName: " + suggestedTitle;
  303.         dialogMessage += "\nSearch Category: " + suggestedCategory;
  304.         dialogMessage += "\nSource: " + engineURL;
  305.     }
  306.           
  307.     var rv = this.promptService.confirm(null, titleMessage, dialogMessage);
  308.       
  309.     if (!rv)
  310.         return;
  311.  
  312.     var internetSearch = Components.classes[NETSEARCH_CONTRACTID].getService();
  313.     if (internetSearch)    
  314.         internetSearch = internetSearch.QueryInterface(nsIInternetSearchService);
  315.     if (internetSearch)
  316.     {
  317.         internetSearch.AddSearchEngine(engineURL, iconURL, suggestedTitle,
  318.                                        suggestedCategory);
  319.     }
  320. }
  321.  
  322. // property of nsIClassInfo
  323. nsSidebar.prototype.flags = nsIClassInfo.DOM_OBJECT;
  324.  
  325. // property of nsIClassInfo
  326. nsSidebar.prototype.classDescription = "Sidebar";
  327.  
  328. // method of nsIClassInfo
  329. nsSidebar.prototype.getInterfaces = function(count) {
  330.     var interfaceList = [nsISidebar, nsIClassInfo];
  331.     count.value = interfaceList.length;
  332.     return interfaceList;
  333. }
  334.  
  335. // method of nsIClassInfo
  336. nsSidebar.prototype.getHelperForLanguage = function(count) {return null;}
  337.  
  338. nsSidebar.prototype.QueryInterface =
  339. function (iid) {
  340.     if (!iid.equals(nsISidebar) && 
  341.         !iid.equals(nsIClassInfo) &&
  342.         !iid.equals(nsISupports))
  343.         throw Components.results.NS_ERROR_NO_INTERFACE;
  344.     return this;
  345. }
  346.  
  347. var sidebarModule = new Object();
  348.  
  349. sidebarModule.registerSelf =
  350. function (compMgr, fileSpec, location, type)
  351. {
  352.     debug("registering (all right -- a JavaScript module!)");
  353.     compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  354.  
  355.     compMgr.registerFactoryLocation(SIDEBAR_CID, 
  356.                                     "Sidebar JS Component",
  357.                                     SIDEBAR_CONTRACTID, 
  358.                                     fileSpec, 
  359.                                     location,
  360.                                     type);
  361.     const CATMAN_CONTRACTID = "@mozilla.org/categorymanager;1";
  362.     const nsICategoryManager = Components.interfaces.nsICategoryManager;
  363.     var catman = Components.classes[CATMAN_CONTRACTID].
  364.                             getService(nsICategoryManager);
  365.                             
  366.     const JAVASCRIPT_GLOBAL_PROPERTY_CATEGORY = "JavaScript global property";
  367.     catman.addCategoryEntry(JAVASCRIPT_GLOBAL_PROPERTY_CATEGORY,
  368.                             "sidebar",
  369.                             SIDEBAR_CONTRACTID,
  370.                             true,
  371.                             true);
  372. }
  373.  
  374. sidebarModule.getClassObject =
  375. function (compMgr, cid, iid) {
  376.     if (!cid.equals(SIDEBAR_CID))
  377.         throw Components.results.NS_ERROR_NO_INTERFACE;
  378.     
  379.     if (!iid.equals(Components.interfaces.nsIFactory))
  380.         throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  381.     
  382.     return sidebarFactory;
  383. }
  384.  
  385. sidebarModule.canUnload =
  386. function(compMgr)
  387. {
  388.     debug("Unloading component.");
  389.     return true;
  390. }
  391.     
  392. /* factory object */
  393. var sidebarFactory = new Object();
  394.  
  395. sidebarFactory.createInstance =
  396. function (outer, iid) {
  397.     debug("CI: " + iid);
  398.     if (outer != null)
  399.         throw Components.results.NS_ERROR_NO_AGGREGATION;
  400.  
  401.     return (new nsSidebar()).QueryInterface(iid);
  402. }
  403.  
  404. /* entrypoint */
  405. function NSGetModule(compMgr, fileSpec) {
  406.     return sidebarModule;
  407. }
  408.  
  409. /* static functions */
  410. if (DEBUG)
  411.     debug = function (s) { dump("-*- sidebar component: " + s + "\n"); }
  412. else
  413.     debug = function (s) {}
  414.  
  415. function getSidebarDatasourceURI(panels_file_id)
  416. {
  417.     try 
  418.     {
  419.         /* use the fileLocator to look in the profile directory 
  420.          * to find 'panels.rdf', which is the
  421.          * database of the user's currently selected panels. */
  422.         var directory_service = Components.classes[DIR_SERV_CONTRACTID].getService(Components.interfaces.nsIProperties);
  423.  
  424.         /* if <profile>/panels.rdf doesn't exist, get will copy
  425.          *bin/defaults/profile/panels.rdf to <profile>/panels.rdf */
  426.         var sidebar_file = directory_service.get(panels_file_id, Components.interfaces.nsIFile);
  427.  
  428.         if (!sidebar_file.exists())
  429.         {
  430.             /* this should not happen, as GetFileLocation() should copy
  431.              * defaults/panels.rdf to the users profile directory */
  432.             debug("sidebar file does not exist");
  433.             return null;
  434.         }
  435.  
  436.         var io_service = Components.classes[IO_SERV_CONTRACTID].getService(Components.interfaces.nsIIOService);
  437.         var file_handler = io_service.getProtocolHandler("file").QueryInterface(Components.interfaces.nsIFileProtocolHandler);
  438.         var sidebar_uri = file_handler.getURLSpecFromFile(sidebar_file);
  439.         debug("sidebar uri is " + sidebar_uri);
  440.         return sidebar_uri;
  441.     }
  442.     catch (ex)
  443.     {
  444.         /* this should not happen */
  445.         debug("caught " + ex + " getting sidebar datasource uri");
  446.         return null;
  447.     }
  448. }
  449. var strBundleService = null;
  450. function srGetStrBundle(path)
  451. {
  452.    var strBundle = null;
  453.    if (!strBundleService) {
  454.        try {
  455.           strBundleService =
  456.           Components.classes["@mozilla.org/intl/stringbundle;1"].getService(); 
  457.           strBundleService = 
  458.           strBundleService.QueryInterface(Components.interfaces.nsIStringBundleService);
  459.        } catch (ex) {
  460.           dump("\n--** strBundleService failed: " + ex + "\n");
  461.           return null;
  462.       }
  463.    }
  464.    strBundle = strBundleService.createBundle(path); 
  465.    if (!strBundle) {
  466.        dump("\n--** strBundle createInstance failed **--\n");
  467.    }
  468.    return strBundle;
  469. }
  470.