michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: Components.utils.import("resource://gre/modules/Services.jsm"); michael@0: Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); michael@0: michael@0: const DEBUG = false; /* set to false to suppress debug messages */ michael@0: michael@0: const SIDEBAR_CONTRACTID = "@mozilla.org/sidebar;1"; michael@0: const SIDEBAR_CID = Components.ID("{22117140-9c6e-11d3-aaf1-00805f8a4905}"); michael@0: michael@0: // File extension for Sherlock search plugin description files michael@0: const SHERLOCK_FILE_EXT_REGEXP = /\.src$/i; michael@0: michael@0: function nsSidebar() michael@0: { michael@0: } michael@0: michael@0: nsSidebar.prototype.classID = SIDEBAR_CID; michael@0: michael@0: nsSidebar.prototype.validateSearchEngine = michael@0: function (engineURL, iconURL) michael@0: { michael@0: try michael@0: { michael@0: // Make sure the URLs are HTTP, HTTPS, or FTP. michael@0: var isWeb = /^(https?|ftp):\/\//i; michael@0: michael@0: if (!isWeb.test(engineURL)) michael@0: throw "Unsupported search engine URL"; michael@0: michael@0: if (iconURL && !isWeb.test(iconURL)) michael@0: throw "Unsupported search icon URL."; michael@0: } michael@0: catch(ex) michael@0: { michael@0: debug(ex); michael@0: Components.utils.reportError("Invalid argument passed to window.sidebar.addSearchEngine: " + ex); michael@0: michael@0: var searchBundle = Services.strings.createBundle("chrome://global/locale/search/search.properties"); michael@0: var brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties"); michael@0: var brandName = brandBundle.GetStringFromName("brandShortName"); michael@0: var title = searchBundle.GetStringFromName("error_invalid_engine_title"); michael@0: var msg = searchBundle.formatStringFromName("error_invalid_engine_msg", michael@0: [brandName], 1); michael@0: Services.ww.getNewPrompter(null).alert(title, msg); michael@0: return false; michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: // The suggestedTitle and suggestedCategory parameters are ignored, but remain michael@0: // for backward compatibility. michael@0: nsSidebar.prototype.addSearchEngine = michael@0: function (engineURL, iconURL, suggestedTitle, suggestedCategory) michael@0: { michael@0: debug("addSearchEngine(" + engineURL + ", " + iconURL + ", " + michael@0: suggestedCategory + ", " + suggestedTitle + ")"); michael@0: michael@0: if (!this.validateSearchEngine(engineURL, iconURL)) michael@0: return; michael@0: michael@0: // OpenSearch files will likely be far more common than Sherlock files, and michael@0: // have less consistent suffixes, so we assume that ".src" is a Sherlock michael@0: // (text) file, and anything else is OpenSearch (XML). michael@0: var dataType; michael@0: if (SHERLOCK_FILE_EXT_REGEXP.test(engineURL)) michael@0: dataType = Components.interfaces.nsISearchEngine.DATA_TEXT; michael@0: else michael@0: dataType = Components.interfaces.nsISearchEngine.DATA_XML; michael@0: michael@0: Services.search.addEngine(engineURL, dataType, iconURL, true); michael@0: } michael@0: michael@0: // This function exists largely to implement window.external.AddSearchProvider(), michael@0: // to match other browsers' APIs. The capitalization, although nonstandard here, michael@0: // is therefore important. michael@0: nsSidebar.prototype.AddSearchProvider = michael@0: function (aDescriptionURL) michael@0: { michael@0: // Get the favicon URL for the current page, or our best guess at the current michael@0: // page since we don't have easy access to the active document. Most search michael@0: // engines will override this with an icon specified in the OpenSearch michael@0: // description anyway. michael@0: var win = Services.wm.getMostRecentWindow("navigator:browser"); michael@0: var browser = win.gBrowser; michael@0: var iconURL = ""; michael@0: // Use documentURIObject in the check for shouldLoadFavIcon so that we michael@0: // do the right thing with about:-style error pages. Bug 453442 michael@0: if (browser.shouldLoadFavIcon(browser.selectedBrowser michael@0: .contentDocument michael@0: .documentURIObject)) michael@0: iconURL = browser.getIcon(); michael@0: michael@0: if (!this.validateSearchEngine(aDescriptionURL, iconURL)) michael@0: return; michael@0: michael@0: const typeXML = Components.interfaces.nsISearchEngine.DATA_XML; michael@0: Services.search.addEngine(aDescriptionURL, typeXML, iconURL, true); michael@0: } michael@0: michael@0: // This function exists to implement window.external.IsSearchProviderInstalled(), michael@0: // for compatibility with other browsers. It will return an integer value michael@0: // indicating whether the given engine is installed for the current user. michael@0: // However, it is currently stubbed out due to security/privacy concerns michael@0: // stemming from difficulties in determining what domain issued the request. michael@0: // See bug 340604 and michael@0: // http://msdn.microsoft.com/en-us/library/aa342526%28VS.85%29.aspx . michael@0: // XXX Implement this! michael@0: nsSidebar.prototype.IsSearchProviderInstalled = michael@0: function (aSearchURL) michael@0: { michael@0: return 0; michael@0: } michael@0: michael@0: nsSidebar.prototype.QueryInterface = XPCOMUtils.generateQI([Components.interfaces.nsISupports]); michael@0: michael@0: this.NSGetFactory = XPCOMUtils.generateNSGetFactory([nsSidebar]); michael@0: michael@0: /* static functions */ michael@0: if (DEBUG) michael@0: debug = function (s) { dump("-*- sidebar component: " + s + "\n"); } michael@0: else michael@0: debug = function (s) {}