home *** CD-ROM | disk | FTP | other *** search
/ PC World 2005 December / PCWorld_2005-12_cd.bin / komunikace / netscape / nsb-install-8-0.exe / chrome / browser.jar / content / browser / search.js < prev    next >
Text File  |  2005-09-26  |  16KB  |  477 lines

  1. var search = {
  2.  
  3.     // Set this to false to disable debug output
  4.     SEARCH_DEBUG : false,
  5.  
  6.     // Constants
  7.     MAX_HISTORY_SIZE : 10,
  8.     SEARCH_PLUGINS_FOLDER : "searchplugins",
  9.     SEARCH_PROVIDER_RDF_FILE : "search-providers.rdf",
  10.     SEARCH_HISTORY_FILE : "search-history.txt",
  11.  
  12.     // File open flags (from prio.h)
  13.     PR_RDONLY : 1,
  14.     PR_WRONLY : 2,
  15.     PR_TRUNCATE : 4,
  16.  
  17.     // RDF Predicates
  18.     SPUI_NS : "http://home.netscape.com/NC-spui#",
  19.     RES_NAME : null,
  20.     RES_ICON : null,
  21.     RES_SRC : null,
  22.  
  23.     // Globals
  24.     profileDir : null,
  25.     ioService : null,
  26.     prefService : null,
  27.     RDFService : null,
  28.     httpService : null,
  29.     localRDFLoadObserver : null,
  30.     remoteRDFLoadObserver : null,
  31.     remoteRDFFetchURL : null,
  32.  
  33.  
  34.     Init : function() {
  35.         this.debug('Init()');
  36.  
  37.         // Get the user's profile directory
  38.         if (!this.profileDir) {
  39.             this.profileDir = Components.classes["@mozilla.org/file/directory_service;1"]
  40.                                         .getService(Components.interfaces.nsIProperties)
  41.                                         .get("ProfD", Components.interfaces.nsILocalFile);
  42.         }
  43.         this.debug(' profileDir: '+this.profileDir.path);
  44.  
  45.         // IO Service
  46.         if (!this.ioService) {
  47.             this.ioService = Components.classes["@mozilla.org/network/io-service;1"]
  48.                                        .getService(Components.interfaces.nsIIOService);
  49.         }
  50.  
  51.         // Pref Service
  52.         if (!this.prefService) {
  53.             this.prefService = Components.classes["@mozilla.org/preferences-service;1"]
  54.                                          .getService(Components.interfaces.nsIPrefBranch);
  55.         }
  56.  
  57.         // RDF Service
  58.         if (!this.RDFService) {
  59.             this.RDFService = Components.classes["@mozilla.org/rdf/rdf-service;1"]
  60.                                         .getService(Components.interfaces.nsIRDFService);
  61.         }
  62.  
  63.         // HTTP Service
  64.         if (!this.httpService) {
  65.             this.httpService = Components.classes["@mozilla.org/network/protocol;1?name=http"]
  66.                                          .getService(Components.interfaces.nsIHttpProtocolHandler);
  67.         }
  68.  
  69.         // RDF Predicates
  70.         this.RES_NAME = this.RDFService.GetResource(this.SPUI_NS+'name');
  71.         this.RES_ICON = this.RDFService.GetResource(this.SPUI_NS+'icon');
  72.         this.RES_SRC = this.RDFService.GetResource(this.SPUI_NS+'src');
  73.  
  74.         // Local RDF Load Observer
  75.         // ... watches loading of the *local* search-providers.rdf file
  76.         if (!this.localRDFLoadObserver) {
  77.             this.debug(' instanciating local RDF load observer');
  78.             this.localRDFLoadObserver = {
  79.                 onBeginLoad : function(sink){},
  80.                 onInterrupt : function(sink){},
  81.                 onResume : function(sink){},
  82.                 onError : function(sink,status,msg){},
  83.                 onEndLoad : function(sink) {
  84.                     this.debug('onEndLoad()');
  85.                     // Load datasource
  86.                     sink.removeXMLSinkObserver(this);
  87.                     sink.QueryInterface(Components.interfaces.nsIRDFDataSource);
  88.                     this.debug(' loaded local datasource: '+sink.URI);
  89.                     // Parse the datasource
  90.                     this.parent.ParseDataSource(sink);
  91.                     // Now update from the server
  92.                     this.parent.LoadRemoteSearchProviders();
  93.                 },
  94.                 debug : function(msg) {
  95.                     this.parent.debug('localRDFLoadObserver: '+msg);
  96.                 }
  97.             };
  98.             this.localRDFLoadObserver.parent = this;
  99.         }
  100.  
  101.         // Remote RDF Load Observer
  102.         // ... watches loading of the *remote* search-providers.rdf file
  103.         if (!this.remoteRDFLoadObserver) {
  104.             this.debug(' instanciating remote RDF load observer');
  105.             this.remoteRDFLoadObserver = {
  106.                 onBeginLoad : function(sink){},
  107.                 onInterrupt : function(sink){},
  108.                 onResume : function(sink){},
  109.                 onError : function(sink,status,msg){},
  110.                 onEndLoad : function(sink) {
  111.                     this.debug('onEndLoad()');
  112.                     // Load datasource
  113.                     sink.removeXMLSinkObserver(this);
  114.                     sink.QueryInterface(Components.interfaces.nsIRDFDataSource);
  115.                     this.debug(' loaded remote datasource: '+sink.URI);
  116.                     // Copy over top of the local file
  117.                     var localFile = this.parent.GetLocalSearchProviderRDFFile();
  118.                     this.debug(' saving a local copy of the RDF file');
  119.                     var localFileURI = this.parent.ioService.newFileURI(localFile);
  120.                     sink.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
  121.                     sink.FlushTo(localFileURI.spec);
  122.                     // Parse the datasource
  123.                     this.parent.ParseDataSource(sink);
  124.                 },
  125.                 debug : function(msg) {
  126.                     this.parent.debug('remoteRDFLoadObserver: '+msg);
  127.                 }
  128.             };
  129.             this.remoteRDFLoadObserver.parent = this;
  130.         }
  131.  
  132.         // Construct URL to fetch the remote search provider RDF file
  133.         if (!this.remoteRDFFetchURL) {
  134.             var user_guid = this.prefService.getCharPref("browser.info.guid");
  135.             var partnerId;
  136.             try {
  137.                 partnerId = this.prefService.getCharPref("browser.partnerId");
  138.             } catch (ex) {
  139.                 partnerId = 'chapera';
  140.             }
  141.             this.remoteRDFFetchURL =
  142.                 this.prefService.getCharPref("browser.search.providers.url");
  143.                 // + "?guid="+user_guid + "&partnerId="+partnerId;
  144.             this.debug(' remote RDF URL: '+this.remoteRDFFetchURL);
  145.         }
  146.  
  147.         this.LoadLocalSearchProviders();
  148.     },
  149.  
  150.  
  151.     LoadLocalSearchProviders : function() {
  152.         this.debug('RefreshLocalSearchProviders()');
  153.         var file = this.GetLocalSearchProviderRDFFile();
  154.         var fileURI = this.ioService.newFileURI(file);
  155.         try {
  156.             // Start loading local RDF file of search providers
  157.             var ds = this.RDFService.GetDataSource(fileURI.spec);
  158.             // Register a listener to pick things up when the file is done
  159.             // loading.  (Control will go to the onEndLoad function...)
  160.             ds.QueryInterface(Components.interfaces.nsIRDFXMLSink);
  161.             ds.addXMLSinkObserver(this.localRDFLoadObserver);
  162.         } catch (ex) {
  163.             // If there was a problem loading the local file, just go
  164.             // directly to the online one
  165.             this.debug(' problem loading local '+this.SEARCH_PROVIDER_RDF_FILE);
  166.             this.LoadRemoteSearchProviders();
  167.         }
  168.     },
  169.  
  170.  
  171.     LoadRemoteSearchProviders : function() {
  172.         this.debug('RefreshRemoteSearchProviders()');
  173.         try {
  174.             ds = this.RDFService.GetDataSource(this.remoteRDFFetchURL);
  175.             ds.QueryInterface(Components.interfaces.nsIRDFXMLSink);
  176.             ds.addXMLSinkObserver(this.remoteRDFLoadObserver);
  177.         } catch (ex) {
  178.             this.debug(' problem loading remote search providers file');
  179.         }
  180.     },
  181.  
  182.  
  183.     ParseDataSource : function(datasource) {
  184.         // Iterate through resources
  185.         var resources = datasource.GetAllResources();
  186.         var res;
  187.         while (resources.hasMoreElements()) {
  188.             res = resources.getNext();
  189.             res.QueryInterface(Components.interfaces.nsIRDFResource);
  190.             this.LoadSingleProviderResource(datasource, res);
  191.             this.RDFService.UnregisterResource(res);
  192.         }
  193.         this.RDFService.UnregisterDataSource(datasource);
  194.     },
  195.  
  196.  
  197.     LoadSingleProviderResource : function(datasource, resource) {
  198.         this.debug('LoadSingleProviderResource('+resource.Value+')');
  199.         // See if this resource specifies an actual search provider
  200.         if (datasource.hasArcOut(resource, this.RES_NAME) &&
  201.             datasource.hasArcOut(resource, this.RES_ICON) &&
  202.             datasource.hasArcOut(resource, this.RES_SRC))
  203.         {
  204.             var name = datasource.GetTarget(resource, this.RES_NAME, true);
  205.             name.QueryInterface(Components.interfaces.nsIRDFLiteral);
  206.             this.debug(' name: '+name.Value);
  207.             var icon = datasource.GetTarget(resource, this.RES_ICON, true);
  208.             icon.QueryInterface(Components.interfaces.nsIRDFLiteral);
  209.             this.debug(' icon: '+icon.Value);
  210.             var src = datasource.GetTarget(resource, this.RES_SRC, true);
  211.             src.QueryInterface(Components.interfaces.nsIRDFLiteral);
  212.             this.debug(' src: '+src.Value);
  213.             // Create the searchplugins folder if it doesn't exist
  214.             var pluginsFolder = this.EnsureSearchPluginsFolderExists();
  215.             // Download the icon and src files and stick them in the
  216.             // searchplugins folder
  217.             this.DownloadToSearchPluginsFolder(icon.Value, ["gif", "jpg", "bmp", "png"]);
  218.             this.DownloadToSearchPluginsFolder(src.Value);
  219.         }
  220.     },
  221.  
  222.  
  223.     DownloadToSearchPluginsFolder : function(urlSpec, clearFiles) {
  224.         this.debug('DownloadToSearchPluginsFolder('+urlSpec+')');
  225.  
  226.         // Create URL object
  227.         var remoteURL = Components.classes["@mozilla.org/network/standard-url;1"]
  228.                                   .createInstance(Components.interfaces.nsIStandardURL);
  229.         remoteURL.init(Components.interfaces.nsIStandardURL.URLTYPE_STANDARD,
  230.                        null, urlSpec, null, null);
  231.         remoteURL.QueryInterface(Components.interfaces.nsIURL);
  232.         this.debug(' filename is: '+remoteURL.fileName);
  233.  
  234.         // Download
  235.         var downloadObserver = {
  236.             QueryInterface : function(iid) {
  237.                 if (!iid.equals(nsIDownloadObserver) &&
  238.                     !iid.equals(nsISupports))
  239.                     throw Components.results.NS_ERROR_NO_INTERFACE;
  240.                 return this;
  241.             },
  242.             onDownloadComplete : function(downloader, request, ctxt, status, file) {
  243.                 // file.path now references a temporary cached copy of the file,
  244.                 // so copy it to the searchplugins folder
  245.                 this.debug('file is at: '+file.path);
  246.                 var pluginsFolder = this.parent.GetSearchPluginsFolder();
  247.                 this.debug('copying to: '+pluginsFolder.path+' '+this.fileName);
  248.                 
  249.                 // BLT 152031 fix: replace the existing icon files
  250.                 if(!clearFiles) {
  251.                     clearFiles = [""];
  252.                 }
  253.                 
  254.                 for(var i in clearFiles) {
  255.                     var ext = clearFiles[i];
  256.                     var destFname = this.fileName;
  257.                     if(ext != "") {
  258.                         var ind = destFname.lastIndexOf(".");
  259.                         if(ind >= 0) {
  260.                             destFname = destFname.substring(0, ind);
  261.                         }
  262.                         destFname += "." + ext;
  263.                     }
  264.                     // Test if the file already exists
  265.                     var destinationFile = pluginsFolder.clone();
  266.                     destinationFile.append(destFname);
  267.                     if (destinationFile.exists()) {
  268.                         this.debug(' (removing pre-existing file: '+destFname+')');
  269.                         destinationFile.remove(false);
  270.                         file.copyTo(pluginsFolder, destFname);  
  271.                     }    
  272.                     else if(this.fileName == destFname) {          
  273.                         file.copyTo(pluginsFolder, destFname); 
  274.                     }
  275.                 }
  276.             },
  277.             debug : function(msg) {
  278.                 this.parent.debug('downloadObserver: '+msg);
  279.             }
  280.         };
  281.         downloadObserver.parent = this;
  282.         downloadObserver.fileName = remoteURL.fileName;
  283.         var channel = this.ioService.newChannel(remoteURL.spec, null, null);
  284.         var downloader = Components.classes["@mozilla.org/network/downloader;1"]
  285.                                    .createInstance(Components.interfaces.nsIDownloader);
  286.         downloader.init(downloadObserver, null);
  287.         channel.asyncOpen(downloader, null);
  288.     },
  289.  
  290.  
  291.     GetSearchPluginsFolder : function() {
  292.         this.debug('GetSearchPluginsFolder()');
  293.         // Create file descriptor
  294.         var folder = this.profileDir.clone();
  295.         folder.append(this.SEARCH_PLUGINS_FOLDER);
  296.         return folder; // returns nsILocalFile
  297.     },
  298.  
  299.  
  300.     EnsureSearchPluginsFolderExists : function() {
  301.         this.debug('EnsureSearchPluginsFolderExists()');
  302.         var folder = this.GetSearchPluginsFolder();
  303.         if (!folder.exists()) {
  304.             folder.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0);
  305.         }
  306.         return folder; // returns nsILocalFile
  307.     },
  308.  
  309.  
  310.     GetLocalSearchProviderRDFFile : function() {
  311.         this.debug('GetLocalSearchProviderRDFFile(): '+this.SEARCH_PROVIDER_RDF_FILE);
  312.         // Create file descriptor
  313.         var file = this.profileDir.clone();
  314.         file.append(this.SEARCH_PROVIDER_RDF_FILE);
  315.         return file; // returns nsILocalFile
  316.     },
  317.  
  318.  
  319.     GetSearchHistoryFile : function() {
  320.         this.debug('GetSearchHistoryFile(): '+this.SEARCH_HISTORY_FILE);
  321.         // Create file descriptor
  322.         var file = this.profileDir.clone();
  323.         file.append(this.SEARCH_HISTORY_FILE);
  324.         return file; // returns nsILocalFile
  325.     },
  326.  
  327.  
  328.     EnsureSearchHistoryFileExists : function() {
  329.         this.debug('EnsureSearchHistoryFileExists()');
  330.         var file = this.GetSearchHistoryFile();
  331.         if (!file.exists()) {
  332.             this.debug(' creating file: '+this.SEARCH_HISTORY_FILE);
  333.             file.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0);
  334.         }
  335.         return file; // returns nsILocalFile
  336.     },
  337.  
  338.  
  339.     ReadSearchHistory : function() {
  340.         this.debug('ReadSearchHistory()');
  341.  
  342.         var file = this.EnsureSearchHistoryFileExists();
  343.  
  344.         // Init the file input stream
  345.         var fis = Components.classes["@mozilla.org/network/file-input-stream;1"]
  346.                             .createInstance(Components.interfaces.nsIFileInputStream);
  347.         fis.init(file, this.PR_RDONLY, 0, 0);
  348.  
  349.         // Init a scriptable input stream
  350.         var sis = Components.classes["@mozilla.org/scriptableinputstream;1"]
  351.                             .createInstance(Components.interfaces.nsIScriptableInputStream);
  352.         sis.init(fis);
  353.  
  354.         // Read the file
  355.         var fileContents = sis.read(sis.available());
  356.  
  357.         // Close file
  358.         fis.close();
  359.  
  360.         // Return the lines as an array
  361.         return fileContents.split('\n');
  362.     },
  363.  
  364.  
  365.     PopulateHistoryPopup : function(evt) {
  366.         this.debug('PopulateHistoryPopup()');
  367.  
  368.         // Purge the history menu
  369.         var popup = evt.target;
  370.         while (popup.lastChild)
  371.             popup.removeChild(popup.lastChild);
  372.  
  373.         // Load in the fresh history items
  374.         var entries = this.ReadSearchHistory();
  375.         for (var i = 0; i < entries.length; i++) {
  376.             if (!entries[i].length) continue;
  377.             var newItem = document.createElement('menuitem');
  378.             newItem.setAttribute('label', entries[i]);
  379.             newItem.setAttribute('oncommand', 'search.HistoryCommand("'+entries[i]+'");');
  380.             popup.appendChild(newItem);
  381.         }
  382.  
  383.         // Only add the separator if there were history items
  384.         if (popup.lastChild)
  385.             popup.appendChild(document.createElement('menuseparator'));
  386.  
  387.         // Always add the 'clear history' menu item
  388.         var clearHist = document.createElement('menuitem');
  389.         clearHist.setAttribute('label', 'Clear Search History');
  390.         clearHist.setAttribute('oncommand', 'search.ClearSearchHistory();');
  391.  
  392.         // ... but if there were no history items, then make it disabled
  393.         if (!popup.lastChild)
  394.             clearHist.setAttribute('disabled','true');
  395.         popup.appendChild(clearHist);
  396.     },
  397.  
  398.  
  399.     HistoryCommand : function(value) {
  400.         this.debug('HistoryCommand("'+value+'")');
  401.         var searchbar = document.getElementById('searchbar');
  402.         if (searchbar) {
  403.             // Put the value into the text box
  404.             searchbar.mTextbox.value = value;
  405.             // Execute search
  406.             searchbar.mTextbox.onTextEntered();
  407.         }
  408.     },
  409.  
  410.  
  411.     AddToHistory : function(value) {
  412.         this.debug('AddToHistory("'+value+'")');
  413.  
  414.         // If it's whitespace, don't bother
  415.         if (!this.trim(value).length) return;
  416.  
  417.         // Create the new list
  418.         var oldList = this.ReadSearchHistory();
  419.         var newList = new Array();
  420.         newList[0] = value;
  421.         for (var i = 0; i < oldList.length; i++) {
  422.             if (oldList[i] != value)
  423.                 newList[newList.length] = oldList[i];
  424.             if (newList.length >= this.MAX_HISTORY_SIZE)
  425.                 break;
  426.         }
  427.  
  428.         // Open the history file for writing
  429.         var file = this.GetSearchHistoryFile();
  430.         file.remove(false);
  431.         file = this.EnsureSearchHistoryFileExists();
  432.         var fos = Components.classes["@mozilla.org/network/file-output-stream;1"]
  433.                             .createInstance(Components.interfaces.nsIFileOutputStream);
  434.         fos.init(file, this.PR_WRONLY, 0, 0);
  435.         var contents = newList.join('\n');
  436.         this.debug(' - writing contents:\n'+contents+'\n\n');
  437.         fos.write(contents, contents.length);
  438.         fos.close();
  439.     },
  440.  
  441.  
  442.     ClearSearchHistory : function() {
  443.         this.debug('ClearSearchHistory()');
  444.         var file = this.GetSearchHistoryFile();
  445.         if (file.exists()) {
  446.             // Init the file input stream
  447.             var fis = Components.classes["@mozilla.org/network/file-input-stream;1"]
  448.                                 .createInstance(Components.interfaces.nsIFileInputStream);
  449.             fis.init(file, this.PR_RDONLY, 0,
  450.                      Components.interfaces.nsIFileInputStream.DELETE_ON_CLOSE);
  451.             fis.close();
  452.         }
  453.         // MERC (rpaul) clear the searchbar text
  454.         var searchbar = document.getElementById('searchbar');    
  455.         if (searchbar)
  456.             searchbar.clear();
  457.     },
  458.  
  459.  
  460.     debug : function(msg) {
  461.         if (!this.prefService ||
  462.             (this.prefService.getPrefType("search.debug")) &&
  463.             (this.prefService.getBoolPref("search.debug")) )
  464.         {
  465.             dump('search.js: '+msg+'\n');
  466.         }
  467.     },
  468.  
  469.  
  470.     trim : function(str) {
  471.         if (!str) return "";
  472.         str = str.replace(/^\s+/, "");
  473.         return str.replace(/\s+$/, "");
  474.     }
  475.  
  476. };
  477.