home *** CD-ROM | disk | FTP | other *** search
/ PC World 2006 December / PCWorld_2006-12_cd.bin / komunikace / netscape / nsb-install-8-1-2.exe / components / nsSidebar.js < prev    next >
Text File  |  2006-01-06  |  20KB  |  512 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.         // MERC - TO
  72.         // used during recursive calls to addPanelInternal
  73.         this.tries = 0;
  74.         this.wait = 100;
  75. }
  76.  
  77. nsSidebar.prototype.nc = "http://home.netscape.com/NC-rdf#";
  78.  
  79. nsSidebar.prototype.observe = 
  80. function() {
  81.     // MERC - TO
  82.     // fix for BLT 120064
  83.     this.wait *= 2;
  84.     this.tries++;
  85.     this.addPanelInternal(this.aTitle, this.aContentURL, this.aCustomizeURL, this.aPersist);
  86. }
  87.  
  88. nsSidebar.prototype.isPanel =
  89. function (aContentURL)
  90. {
  91.     var container = 
  92.         Components.classes[CONTAINER_CONTRACTID].createInstance(nsIRDFContainer);
  93.  
  94.     container.Init(this.datasource, this.rdf.GetResource(this.resource));
  95.     
  96.     /* Create a resource for the new panel and add it to the list */
  97.     var panel_resource = 
  98.         this.rdf.GetResource("urn:sidebar:3rdparty-panel:" + aContentURL);
  99.  
  100.     return (container.IndexOf(panel_resource) != -1);
  101. }
  102.  
  103. function sidebarURLSecurityCheck(url)
  104. {
  105.     if (url.search(/(^http:|^ftp:|^https:)/) == -1)
  106.         throw "Script attempted to add sidebar panel from illegal source";
  107. }
  108.  
  109. /* decorate prototype to provide ``class'' methods and property accessors */
  110. nsSidebar.prototype.addPanel =
  111. function (aTitle, aContentURL, aCustomizeURL)
  112. {
  113.     debug("addPanel(" + aTitle + ", " + aContentURL + ", " +
  114.           aCustomizeURL + ")");
  115.    
  116.     return this.addPanelInternal(aTitle, aContentURL, aCustomizeURL, false);
  117. }
  118.  
  119. nsSidebar.prototype.addPersistentPanel = 
  120. function(aTitle, aContentURL, aCustomizeURL)
  121. {
  122.     debug("addPersistentPanel(" + aTitle + ", " + aContentURL + ", " +
  123.            aCustomizeURL + ")\n");
  124.  
  125.     return this.addPanelInternal(aTitle, aContentURL, aCustomizeURL, true);
  126. }
  127.  
  128. /*nsSidebar.prototype.addPanelInternal2 =
  129. function (aTitle, aContentURL, aCustomizeURL, aPersist)
  130. {
  131.     var WINMEDSVC = Components.classes['@mozilla.org/appshell/window-mediator;1']
  132.                               .getService(Components.interfaces.nsIWindowMediator);
  133.     var win = WINMEDSVC.getMostRecentWindow( "navigator:browser" );
  134.                                                                                 
  135.     sidebarURLSecurityCheck(aContentURL);
  136.     win.openDialog("chrome://browser/content/bookmarks/addBookmark2.xul", "",
  137.                    "centerscreen,chrome,dialog,resizable,dependent",
  138.                    aTitle, aContentURL, null, null, null, null, true);
  139. }*/
  140.  
  141. nsSidebar.prototype.addPanelInternal =
  142. function (aTitle, aContentURL, aCustomizeURL, aPersist)
  143. {
  144.     sidebarURLSecurityCheck(aContentURL);
  145.  
  146.     // Create a "container" wrapper around the current panels to
  147.     // manipulate the RDF:Seq more easily.
  148.     var panel_list = this.datasource.GetTarget(this.rdf.GetResource(this.resource), this.rdf.GetResource(nsSidebar.prototype.nc+"panel-list"), true);
  149.     if (panel_list) {
  150.         panel_list.QueryInterface(Components.interfaces.nsIRDFResource);
  151.     }
  152.     else {
  153.             // MERC - TO
  154.             // fix for BLT 120064
  155.       // wait a bit and try to install again
  156.       if(this.tries < 3) {
  157.           // Datasource is busted. Start over.
  158.           debug("Sidebar datasource is busted. Number of tries: " + this.tries+1);
  159.           
  160.                 var c, timer;
  161.                 c = Components.classes["@mozilla.org/timer;1"];
  162.                 if(c) {
  163.                     timer = c.createInstance(Components.interfaces.nsITimer);
  164.                     if(timer) {
  165.                         this.aTitle = aTitle;
  166.                         this.aContentURL = aContentURL;
  167.                         this.aCustomizeURL = aCustomizeURL;
  168.                         this.aPersist = aPersist;
  169.             
  170.                         timer.init(this, this.wait, timer.TYPE_ONE_SHOT);
  171.                         return;
  172.                     }
  173.                 }
  174.             }
  175.  
  176.             //we've tried enough or we failed in trying again, just return;
  177.             this.tries = 0;
  178.             this.wait = 100;
  179.             return;
  180.     }
  181.  
  182.         //reset the initial condition for the next time
  183.         this.tries = 0;
  184.         this.wait = 100;
  185.  
  186.     var container = Components.classes[CONTAINER_CONTRACTID].createInstance(nsIRDFContainer);
  187.     container.Init(this.datasource, panel_list);
  188.  
  189.     /* Create a resource for the new panel and add it to the list */
  190.     var panel_resource = 
  191.         this.rdf.GetResource("urn:sidebar:3rdparty-panel:" + aContentURL);
  192.     var panel_index = container.IndexOf(panel_resource);
  193.     var stringBundle, brandStringBundle, titleMessage, dialogMessage;
  194.     if (panel_index != -1)
  195.     {
  196.         try {
  197.             stringBundle = srGetStrBundle("chrome://browser/locale/sidebar/sidebar.properties");
  198.             //brandStringBundle = srGetStrBundle("chrome://global/locale/brand.properties");
  199.             if (stringBundle) {
  200.                 //sidebarName = brandStringBundle.GetStringFromName("sidebarName");
  201.                 sidebarName = "Sidebar";
  202.                 titleMessage = stringBundle.GetStringFromName("dupePanelAlertTitle");
  203.                 dialogMessage = stringBundle.GetStringFromName("dupePanelAlertMessage");
  204.                 dialogMessage = dialogMessage.replace(/%url%/, aContentURL);
  205.                 dialogMessage = dialogMessage.replace(/%name%/, sidebarName);
  206.             }
  207.         }
  208.         catch (e) {
  209.             titleMessage = "Sidebar";
  210.             dialogMessage = aContentURL + " already exists in Sidebar.  No string bundle";
  211.         }
  212.           
  213.         this.promptService.alert(null, titleMessage, dialogMessage);
  214.  
  215.         return;
  216.     }
  217.  
  218.     try {
  219.         stringBundle = srGetStrBundle("chrome://browser/locale/sidebar/sidebar.properties");
  220.         //brandStringBundle = srGetStrBundle("chrome://global/locale/brand.properties");
  221.         if (stringBundle) {                        
  222.             titleMessage = stringBundle.GetStringFromName("addPanelConfirmTitle");                                    
  223.             dialogMessage = stringBundle.GetStringFromName("addPanelConfirmMessage");                                    
  224.             if (aPersist)
  225.             {
  226.                 var warning = stringBundle.GetStringFromName("persistentPanelWarning");
  227.                 dialogMessage += "\n" + warning;
  228.             }
  229.             dialogMessage = dialogMessage.replace(/%title%/, aTitle);
  230.             dialogMessage = dialogMessage.replace(/%url%/, aContentURL);
  231.             dialogMessage = dialogMessage.replace(/#/g, "\n");
  232.             dialogMessage = dialogMessage.replace(/%name%/g, sidebarName);
  233.         }
  234.     }
  235.     catch (e) {
  236.         titleMessage = "Add Tab to Sidebar";        
  237.     dialogMessage = "Add the Tab '" + aTitle + "' to Sidebar?\n\n" + "Source: " + aContentURL;
  238.  
  239.     }
  240.           
  241.     var rv = this.promptService.confirm(null, titleMessage, dialogMessage);
  242.       
  243.     if (!rv)
  244.         return;
  245.  
  246.     /* Now make some sidebar-ish assertions about it... */
  247.     this.datasource.Assert(panel_resource,
  248.                            this.rdf.GetResource(this.nc + "title"),
  249.                            this.rdf.GetLiteral(aTitle),
  250.                            true);
  251.     this.datasource.Assert(panel_resource,
  252.                            this.rdf.GetResource(this.nc + "content"),
  253.                            this.rdf.GetLiteral(aContentURL),
  254.                            true);
  255.     if (aCustomizeURL)
  256.         this.datasource.Assert(panel_resource,
  257.                                this.rdf.GetResource(this.nc + "customize"),
  258.                                this.rdf.GetLiteral(aCustomizeURL),
  259.                                true);
  260.     var persistValue = aPersist ? "true" : "false";
  261.     this.datasource.Assert(panel_resource,
  262.                            this.rdf.GetResource(this.nc + "persist"),
  263.                            this.rdf.GetLiteral(persistValue),
  264.                            true);
  265.         
  266.     container.AppendElement(panel_resource);
  267.  
  268.     // Use an assertion to pass a "refresh" event to all the sidebars.
  269.     // They use observers to watch for this assertion (in sidebarOverlay.js).
  270.     this.datasource.Assert(this.rdf.GetResource(this.resource),
  271.                            this.rdf.GetResource(this.nc + "refresh"),
  272.                            this.rdf.GetLiteral("true"),
  273.                            true);
  274.     this.datasource.Unassert(this.rdf.GetResource(this.resource),
  275.                              this.rdf.GetResource(this.nc + "refresh"),
  276.                              this.rdf.GetLiteral("true"));
  277.  
  278.     /* Write the modified panels out. */
  279.     this.datasource.QueryInterface(nsIRDFRemoteDataSource).Flush();
  280.  
  281. }
  282.  
  283. /* decorate prototype to provide ``class'' methods and property accessors */
  284. nsSidebar.prototype.addSearchEngine =
  285. function (engineURL, iconURL, suggestedTitle, suggestedCategory)
  286. {
  287.     debug("addSearchEngine(" + engineURL + ", " + iconURL + ", " +
  288.           suggestedCategory + ", " + suggestedTitle + ")");
  289.  
  290.     try
  291.     {
  292.         // make sure using HTTP (for both engine as well as icon URLs)
  293.  
  294.         if (engineURL.search(/^http:\/\//i) == -1)
  295.         {
  296.             debug ("must use HTTP to fetch search engine file");
  297.             throw Components.results.NS_ERROR_INVALID_ARG;
  298.         }
  299.  
  300.         if (iconURL.search(/^http:\/\//i) == -1)
  301.         {
  302.             debug ("must use HTTP to fetch search icon file");
  303.             throw Components.results.NS_ERROR_INVALID_ARG;
  304.         }
  305.  
  306.         // make sure engineURL refers to a .src file
  307.         if (engineURL.search(/\.src$/i) == -1)
  308.         {
  309.             debug ("engineURL doesn't reference a .src file");
  310.             throw Components.results.NS_ERROR_INVALID_ARG;
  311.         }
  312.  
  313.         // make sure iconURL refers to a .gif/.jpg/.jpeg/.png file
  314.         if (iconURL.search(/\.(gif|jpg|jpeg|png)$/i) == -1)
  315.         {
  316.             debug ("iconURL doesn't reference a supported image file");
  317.             throw Components.results.NS_ERROR_INVALID_ARG;
  318.         }
  319.  
  320.     }
  321.     catch(ex)
  322.     {
  323.         this.promptService.alert(null, "Failed to add the search engine.");
  324.         throw Components.results.NS_ERROR_INVALID_ARG;
  325.     }
  326.  
  327.     var titleMessage, dialogMessage;
  328.     try {
  329.         var stringBundle = srGetStrBundle("chrome://browser/locale/sidebar/sidebar.properties");
  330.         //var brandStringBundle = srGetStrBundle("chrome://global/locale/brand.properties");
  331.         if (stringBundle) {
  332.             //sidebarName = brandStringBundle.GetStringFromName("sidebarName");    
  333.             sidebarName = "Sidebar";        
  334.             titleMessage = stringBundle.GetStringFromName("addEngineConfirmTitle");
  335.             dialogMessage = stringBundle.GetStringFromName("addEngineConfirmMessage");
  336.             dialogMessage = dialogMessage.replace(/%title%/, suggestedTitle);
  337.             dialogMessage = dialogMessage.replace(/%category%/, suggestedCategory);
  338.             dialogMessage = dialogMessage.replace(/%url%/, engineURL);
  339.             dialogMessage = dialogMessage.replace(/#/g, "\n");
  340.             dialogMessage = dialogMessage.replace(/%name%/, sidebarName);
  341.         }
  342.     }
  343.     catch (e) {
  344.         titleMessage = "Add Search Engine";
  345.         dialogMessage = "Add the following search engine?\n\nName: " + suggestedTitle;
  346.         dialogMessage += "\nSearch Category: " + suggestedCategory;
  347.         dialogMessage += "\nSource: " + engineURL;
  348.     }
  349.           
  350.     var rv = this.promptService.confirm(null, titleMessage, dialogMessage);
  351.       
  352.     if (!rv)
  353.         return;
  354.  
  355.     var internetSearch = Components.classes[NETSEARCH_CONTRACTID].getService();
  356.     if (internetSearch)    
  357.         internetSearch = internetSearch.QueryInterface(nsIInternetSearchService);
  358.     if (internetSearch)
  359.     {
  360.         internetSearch.AddSearchEngine(engineURL, iconURL, suggestedTitle,
  361.                                        suggestedCategory);
  362.     }
  363. }
  364.  
  365. // property of nsIClassInfo
  366. nsSidebar.prototype.flags = nsIClassInfo.DOM_OBJECT;
  367.  
  368. // property of nsIClassInfo
  369. nsSidebar.prototype.classDescription = "Sidebar";
  370.  
  371. // method of nsIClassInfo
  372. nsSidebar.prototype.getInterfaces = function(count) {
  373.     var interfaceList = [nsISidebar, nsIClassInfo];
  374.     count.value = interfaceList.length;
  375.     return interfaceList;
  376. }
  377.  
  378. // method of nsIClassInfo
  379. nsSidebar.prototype.getHelperForLanguage = function(count) {return null;}
  380.  
  381. nsSidebar.prototype.QueryInterface =
  382. function (iid) {
  383.     if (!iid.equals(nsISidebar) && 
  384.         !iid.equals(nsIClassInfo) &&
  385.         !iid.equals(nsISupports))
  386.         throw Components.results.NS_ERROR_NO_INTERFACE;
  387.     return this;
  388. }
  389.  
  390. var sidebarModule = new Object();
  391.  
  392. sidebarModule.registerSelf =
  393. function (compMgr, fileSpec, location, type)
  394. {
  395.     debug("registering (all right -- a JavaScript module!)");
  396.     compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  397.  
  398.     compMgr.registerFactoryLocation(SIDEBAR_CID, 
  399.                                     "Sidebar JS Component",
  400.                                     SIDEBAR_CONTRACTID, 
  401.                                     fileSpec, 
  402.                                     location,
  403.                                     type);
  404.     const CATMAN_CONTRACTID = "@mozilla.org/categorymanager;1";
  405.     const nsICategoryManager = Components.interfaces.nsICategoryManager;
  406.     var catman = Components.classes[CATMAN_CONTRACTID].
  407.                             getService(nsICategoryManager);
  408.                             
  409.     const JAVASCRIPT_GLOBAL_PROPERTY_CATEGORY = "JavaScript global property";
  410.     catman.addCategoryEntry(JAVASCRIPT_GLOBAL_PROPERTY_CATEGORY,
  411.                             "sidebar",
  412.                             SIDEBAR_CONTRACTID,
  413.                             true,
  414.                             true);
  415. }
  416.  
  417. sidebarModule.getClassObject =
  418. function (compMgr, cid, iid) {
  419.     if (!cid.equals(SIDEBAR_CID))
  420.         throw Components.results.NS_ERROR_NO_INTERFACE;
  421.     
  422.     if (!iid.equals(Components.interfaces.nsIFactory))
  423.         throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  424.     
  425.     return sidebarFactory;
  426. }
  427.  
  428. sidebarModule.canUnload =
  429. function(compMgr)
  430. {
  431.     debug("Unloading component.");
  432.     return true;
  433. }
  434.     
  435. /* factory object */
  436. var sidebarFactory = new Object();
  437.  
  438. sidebarFactory.createInstance =
  439. function (outer, iid) {
  440.     debug("CI: " + iid);
  441.     if (outer != null)
  442.         throw Components.results.NS_ERROR_NO_AGGREGATION;
  443.  
  444.     return (new nsSidebar()).QueryInterface(iid);
  445. }
  446.  
  447. /* entrypoint */
  448. function NSGetModule(compMgr, fileSpec) {
  449.     return sidebarModule;
  450. }
  451.  
  452. /* static functions */
  453. if (DEBUG)
  454.     debug = function (s) { dump("-*- sidebar component: " + s + "\n"); }
  455. else
  456.     debug = function (s) {}
  457.  
  458. function getSidebarDatasourceURI(panels_file_id)
  459. {
  460.     try 
  461.     {
  462.         /* use the fileLocator to look in the profile directory 
  463.          * to find 'panels.rdf', which is the
  464.          * database of the user's currently selected panels. */
  465.         var directory_service = Components.classes[DIR_SERV_CONTRACTID].getService(Components.interfaces.nsIProperties);
  466.  
  467.         /* if <profile>/panels.rdf doesn't exist, get will copy
  468.          *bin/defaults/profile/panels.rdf to <profile>/panels.rdf */
  469.         var sidebar_file = directory_service.get(panels_file_id, Components.interfaces.nsIFile);
  470.  
  471.         if (!sidebar_file.exists())
  472.         {
  473.             /* this should not happen, as GetFileLocation() should copy
  474.              * defaults/panels.rdf to the users profile directory */
  475.             debug("sidebar file does not exist");
  476.             return null;
  477.         }
  478.  
  479.         var io_service = Components.classes[IO_SERV_CONTRACTID].getService(Components.interfaces.nsIIOService);
  480.         var file_handler = io_service.getProtocolHandler("file").QueryInterface(Components.interfaces.nsIFileProtocolHandler);
  481.         var sidebar_uri = file_handler.getURLSpecFromFile(sidebar_file);
  482.         debug("sidebar uri is " + sidebar_uri);
  483.         return sidebar_uri;
  484.     }
  485.     catch (ex)
  486.     {
  487.         /* this should not happen */
  488.         debug("caught " + ex + " getting sidebar datasource uri");
  489.         return null;
  490.     }
  491. }
  492. var strBundleService = null;
  493. function srGetStrBundle(path)
  494. {
  495.    var strBundle = null;
  496.    if (!strBundleService) {
  497.        try {
  498.           strBundleService =
  499.           Components.classes["@mozilla.org/intl/stringbundle;1"].getService(); 
  500.           strBundleService = 
  501.           strBundleService.QueryInterface(Components.interfaces.nsIStringBundleService);
  502.        } catch (ex) {
  503.           dump("\n--** strBundleService failed: " + ex + "\n");
  504.           return null;
  505.       }
  506.    }
  507.    strBundle = strBundleService.createBundle(path); 
  508.    if (!strBundle) {
  509.        dump("\n--** strBundle createInstance failed **--\n");
  510.    }
  511.    return strBundle;
  512. }