Bug 337780: support window.external.AddSearchProvider('URL'). r=gavin.sharp, ben@mozilla.org
git-svn-id: svn://10.0.0.236/trunk@200166 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
0046223a55
commit
f18ef37a89
@ -61,6 +61,7 @@ const SIDEBAR_CID = Components.ID("{22117140-9c6e-11d3-aaf1-00805f
|
||||
const nsISupports = Components.interfaces.nsISupports;
|
||||
const nsIFactory = Components.interfaces.nsIFactory;
|
||||
const nsISidebar = Components.interfaces.nsISidebar;
|
||||
const nsISidebarExternal = Components.interfaces.nsISidebarExternal;
|
||||
const nsIClassInfo = Components.interfaces.nsIClassInfo;
|
||||
|
||||
function nsSidebar()
|
||||
@ -126,44 +127,94 @@ function (aTitle, aContentURL, aCustomizeURL, aPersist)
|
||||
}
|
||||
|
||||
/* decorate prototype to provide ``class'' methods and property accessors */
|
||||
nsSidebar.prototype.confirmSearchEngine =
|
||||
function (engineURL, suggestedTitle)
|
||||
{
|
||||
var stringBundle = srGetStrBundle("chrome://browser/locale/sidebar/sidebar.properties");
|
||||
var titleMessage = stringBundle.GetStringFromName("addEngineConfirmTitle");
|
||||
var dialogMessage = stringBundle.formatStringFromName("addEngineConfirmText",
|
||||
[suggestedTitle, engineURL], 2);
|
||||
|
||||
return this.promptService.confirm(null, titleMessage, dialogMessage);
|
||||
}
|
||||
|
||||
// The expected suffix for the engine URL should be bare, i.e. without the
|
||||
// leading dot. "src" (for Sherlock files) and "xml" (for OpenSearch files)
|
||||
// are common choices.
|
||||
nsSidebar.prototype.validateSearchEngine =
|
||||
function (engineURL, expectedSuffix, iconURL)
|
||||
{
|
||||
try
|
||||
{
|
||||
// make sure using HTTP or HTTPS and refering to the expected kind of file
|
||||
// for the engine.
|
||||
const engineRegexp = new RegExp("^https?:\/\/.+\." + expectedSuffix + "$", "i");
|
||||
if (! engineRegexp.test(engineURL))
|
||||
throw "Unsupported search engine URL";
|
||||
|
||||
// make sure using HTTP or HTTPS and refering to a
|
||||
// .gif/.jpg/.jpeg/.png/.ico file for the icon.
|
||||
if (iconURL &&
|
||||
! /^https?:\/\/.+\.(gif|jpg|jpeg|png|ico)$/i.test(iconURL))
|
||||
throw "Unsupported search icon URL.";
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
debug(ex);
|
||||
Components.utils.reportError("Invalid argument passed to window.sidebar.addSearchEngine: " + ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsSidebar.prototype.addSearchEngine =
|
||||
function (engineURL, iconURL, suggestedTitle, suggestedCategory)
|
||||
{
|
||||
debug("addSearchEngine(" + engineURL + ", " + iconURL + ", " +
|
||||
suggestedCategory + ", " + suggestedTitle + ")");
|
||||
debug("addSearchEngine(" + engineURL + ", " + iconURL + ", " +
|
||||
suggestedCategory + ", " + suggestedTitle + ")");
|
||||
|
||||
try
|
||||
{
|
||||
// make sure using HTTP or HTTPS and refering to a .src file
|
||||
// for the engine.
|
||||
if (! /^https?:\/\/.+\.src$/i.test(engineURL))
|
||||
throw "Unsupported search engine URL.";
|
||||
if (!this.validateSearchEngine(engineURL, "src", iconURL))
|
||||
return;
|
||||
|
||||
if (!this.confirmSearchEngine(engineURL, suggestedTitle))
|
||||
return;
|
||||
|
||||
var searchService = Components.classes["@mozilla.org/browser/search-service;1"]
|
||||
.getService(Components.interfaces.nsIBrowserSearchService);
|
||||
const typeText = Components.interfaces.nsISearchEngine.DATA_TEXT;
|
||||
if (searchService)
|
||||
searchService.addEngine(engineURL, typeText, iconURL);
|
||||
}
|
||||
|
||||
// make sure using HTTP or HTTPS and refering to a
|
||||
// .gif/.jpg/.jpeg/.png file for the icon.
|
||||
if (! /^https?:\/\/.+\.(gif|jpg|jpeg|png)$/i.test(iconURL))
|
||||
throw "Unsupported search icon URL.";
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
debug(ex);
|
||||
Components.utils.reportError("Invalid argument passed to window.sidebar.addSearchEngine: " + ex);
|
||||
return;
|
||||
}
|
||||
|
||||
var stringBundle = srGetStrBundle("chrome://browser/locale/sidebar/sidebar.properties");
|
||||
var titleMessage = stringBundle.GetStringFromName("addEngineConfirmTitle");
|
||||
var dialogMessage = stringBundle.formatStringFromName("addEngineConfirmText",
|
||||
[suggestedTitle, engineURL], 2);
|
||||
|
||||
if (!this.promptService.confirm(null, titleMessage, dialogMessage))
|
||||
return;
|
||||
|
||||
var searchService = Components.classes["@mozilla.org/browser/search-service;1"]
|
||||
.getService(Components.interfaces.nsIBrowserSearchService);
|
||||
const typeText = Components.interfaces.nsISearchEngine.DATA_TEXT;
|
||||
if (searchService)
|
||||
searchService.addEngine(engineURL, typeText, iconURL);
|
||||
// This function exists largely to implement window.external.AddSearchProvider(),
|
||||
// to match other browsers' APIs. The capitalization, although nonstandard here,
|
||||
// is therefore important.
|
||||
nsSidebar.prototype.AddSearchProvider =
|
||||
function (aDescriptionURL)
|
||||
{
|
||||
// Get the favicon URL for the current page, or our best guess at the current
|
||||
// page since we don't have easy access to the active document. Most search
|
||||
// engines will override this with an icon specified in the OpenSearch
|
||||
// description anyway.
|
||||
var WINMEDSVC = Components.classes['@mozilla.org/appshell/window-mediator;1']
|
||||
.getService(Components.interfaces.nsIWindowMediator);
|
||||
var win = WINMEDSVC.getMostRecentWindow("navigator:browser");
|
||||
var browser = win.document.getElementById("content");
|
||||
var iconURL = "";
|
||||
if (browser.shouldLoadFavIcon(browser.selectedBrowser.currentURI))
|
||||
iconURL = win.gProxyFavIcon.getAttribute("src");
|
||||
|
||||
if (!this.validateSearchEngine(aDescriptionURL, "xml", iconURL))
|
||||
return;
|
||||
|
||||
if (!this.confirmSearchEngine(aDescriptionURL, ""))
|
||||
return;
|
||||
|
||||
var searchService = Components.classes["@mozilla.org/browser/search-service;1"]
|
||||
.getService(Components.interfaces.nsIBrowserSearchService);
|
||||
const typeXML = Components.interfaces.nsISearchEngine.DATA_XML;
|
||||
searchService.addEngine(aDescriptionURL, typeXML, iconURL);
|
||||
}
|
||||
|
||||
nsSidebar.prototype.addMicrosummaryGenerator =
|
||||
@ -196,7 +247,7 @@ nsSidebar.prototype.classDescription = "Sidebar";
|
||||
|
||||
// method of nsIClassInfo
|
||||
nsSidebar.prototype.getInterfaces = function(count) {
|
||||
var interfaceList = [nsISidebar, nsIClassInfo];
|
||||
var interfaceList = [nsISidebar, nsISidebarExternal, nsIClassInfo];
|
||||
count.value = interfaceList.length;
|
||||
return interfaceList;
|
||||
}
|
||||
@ -206,7 +257,8 @@ nsSidebar.prototype.getHelperForLanguage = function(count) {return null;}
|
||||
|
||||
nsSidebar.prototype.QueryInterface =
|
||||
function (iid) {
|
||||
if (!iid.equals(nsISidebar) &&
|
||||
if (!iid.equals(nsISidebar) &&
|
||||
!iid.equals(nsISidebarExternal) &&
|
||||
!iid.equals(nsIClassInfo) &&
|
||||
!iid.equals(nsISupports))
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
@ -238,6 +290,12 @@ function (compMgr, fileSpec, location, type)
|
||||
SIDEBAR_CONTRACTID,
|
||||
true,
|
||||
true);
|
||||
|
||||
catman.addCategoryEntry(JAVASCRIPT_GLOBAL_PROPERTY_CATEGORY,
|
||||
"external",
|
||||
SIDEBAR_CONTRACTID,
|
||||
true,
|
||||
true);
|
||||
}
|
||||
|
||||
sidebarModule.getClassObject =
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(577CB745-8CAF-11d3-AAEF-00805F8A4905)]
|
||||
[scriptable, uuid(577cb745-8caf-11d3-aaef-00805f8a4905)]
|
||||
interface nsISidebar : nsISupports
|
||||
{
|
||||
void addPanel(in wstring aTitle, in string aContentURL,
|
||||
@ -56,6 +56,12 @@ interface nsISidebar : nsISupports
|
||||
void addMicrosummaryGenerator(in string generatorURL);
|
||||
};
|
||||
|
||||
[scriptable, uuid(edd70275-c131-4558-8f6c-9c4716b554a6)]
|
||||
interface nsISidebarExternal : nsISupports
|
||||
{
|
||||
void AddSearchProvider(in string aDescriptionURL);
|
||||
};
|
||||
|
||||
%{ C++
|
||||
// {577CB744-8CAF-11d3-AAEF-00805F8A4905}
|
||||
#define NS_SIDEBAR_CID \
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user