Bug 378553 - Expose search engine alias functionality. r=gavin

This commit is contained in:
rflint@ryanflint.com 2007-06-27 12:25:14 -07:00
Родитель 1fa02e7409
Коммит 81b4505d40
6 изменённых файлов: 190 добавлений и 94 удалений

Просмотреть файл

@ -2003,115 +2003,89 @@ function BrowserLoadURL(aTriggeringEvent, aPostData) {
focusElement(content);
}
function getShortcutOrURI(aURL, aPostDataRef)
{
// rjc: added support for URL shortcuts (3/30/1999)
function getShortcutOrURI(aURL, aPostDataRef) {
var shortcutURL = null;
var keyword = aURL;
var param = "";
var searchService = Cc["@mozilla.org/browser/search-service;1"].
getService(Ci.nsIBrowserSearchService);
var offset = aURL.indexOf(" ");
if (offset > 0) {
keyword = aURL.substr(0, offset);
param = aURL.substr(offset + 1);
}
var engine = searchService.getEngineByAlias(keyword);
if (engine)
return engine.getSubmission(param, null).uri.spec;
try {
var shortcutURL = null;
#ifdef MOZ_PLACES_BOOKMARKS
var shortcutURI = PlacesUtils.bookmarks.getURIForKeyword(aURL);
if (shortcutURI) {
shortcutURL = shortcutURI.spec;
// get POST data
var postData = PlacesUtils.getPostDataForURI(shortcutURI);
aPostDataRef.value = postData;
}
var shortcutURI = PlacesUtils.bookmarks.getURIForKeyword(keyword);
shortcutURL = shortcutURI.spec;
aPostDataRef.value = PlacesUtils.getPostDataForURI(shortcutURI);
#else
shortcutURL = BMSVC.resolveKeyword(aURL, aPostDataRef);
shortcutURL = BMSVC.resolveKeyword(keyword, aPostDataRef);
#endif
if (!shortcutURL) {
// rjc: add support for string substitution with shortcuts (4/4/2000)
// (see bug # 29871 for details)
var aOffset = aURL.indexOf(" ");
if (aOffset > 0) {
var cmd = aURL.substr(0, aOffset);
var text = aURL.substr(aOffset+1);
#ifdef MOZ_PLACES_BOOKMARKS
shortcutURI = PlacesUtils.bookmarks.getURIForKeyword(cmd);
if (shortcutURI)
shortcutURL = shortcutURI.spec;
#else
shortcutURL = BMSVC.resolveKeyword(cmd, aPostDataRef);
#endif
if (shortcutURL && text) {
var encodedText = null;
var charset = "";
const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/;
var matches = shortcutURL.match(re);
if (matches) {
shortcutURL = matches[1];
charset = matches[2];
}
} catch(ex) {}
if (!shortcutURL)
return aURL;
var postData = "";
if (aPostDataRef && aPostDataRef.value)
postData = unescape(aPostDataRef.value);
if (/%s/i.test(shortcutURL) || /%s/i.test(postData)) {
var charset = "";
const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/;
var matches = shortcutURL.match(re);
if (matches)
[, shortcutURL, charset] = matches;
else {
try {
//XXX Bug 317472 will add lastCharset support to places.
#ifndef MOZ_PLACES_BOOKMARKS
// FIXME: Bug #317472, we don't have last charset in places yet.
else if (/%s/.test(shortcutURL) ||
(aPostDataRef && /%s/.test(aPostDataRef.value))) {
try {
charset = BMSVC.getLastCharset(shortcutURL);
} catch (ex) {
}
}
charset = BMSVC.getLastCharset(shortcutURL);
#endif
if (charset)
encodedText = escape(convertFromUnicode(charset, text));
else // default case: charset=UTF-8
encodedText = encodeURIComponent(text);
if (aPostDataRef && aPostDataRef.value) {
// XXXben - currently we only support "application/x-www-form-urlencoded"
// enctypes.
aPostDataRef.value = unescape(aPostDataRef.value);
if (aPostDataRef.value.match(/%[sS]/)) {
aPostDataRef.value = getPostDataStream(aPostDataRef.value,
text, encodedText,
"application/x-www-form-urlencoded");
}
else {
shortcutURL = null;
aPostDataRef.value = null;
}
}
else {
if (/%[sS]/.test(shortcutURL))
shortcutURL = shortcutURL.replace(/%s/g, encodedText)
.replace(/%S/g, text);
else
shortcutURL = null;
}
}
} catch (ex) {
Components.utils.reportError(ex);
}
}
if (shortcutURL)
aURL = shortcutURL;
var encodedParam = "";
if (charset)
encodedParam = escape(converFromUnicode(charset, param));
else // Default charset is UTF-8
encodedParam = encodeURIComponent(param);
} catch (ex) {
shortcutURL = shortcutURL.replace(/%s/g, encodedParam).replace(/%S/g, param);
if (/%s/i.test(postData)) // POST keyword
aPostDataRef.value = getPostDataStream(postData, param, encodedParam,
"application/x-www-form-urlencoded");
}
return aURL;
else
aPostDataRef.value = null;
return shortcutURL;
}
function getPostDataStream(aStringData, aKeyword, aEncKeyword, aType)
{
var dataStream = Components.classes["@mozilla.org/io/string-input-stream;1"]
.createInstance(Components.interfaces.nsIStringInputStream);
function getPostDataStream(aStringData, aKeyword, aEncKeyword, aType) {
var dataStream = Cc["@mozilla.org/io/string-input-stream;1"].
createInstance(Ci.nsIStringInputStream);
aStringData = aStringData.replace(/%s/g, aEncKeyword).replace(/%S/g, aKeyword);
#ifdef MOZILLA_1_8_BRANCH
# bug 318193
dataStream.setData(aStringData, aStringData.length);
#else
dataStream.data = aStringData;
#endif
var mimeStream = Components.classes["@mozilla.org/network/mime-input-stream;1"]
.createInstance(Components.interfaces.nsIMIMEInputStream);
var mimeStream = Cc["@mozilla.org/network/mime-input-stream;1"].
createInstance(Ci.nsIMIMEInputStream);
mimeStream.addHeader("Content-Type", aType);
mimeStream.addContentLength = true;
mimeStream.setData(dataStream);
return mimeStream.QueryInterface(Components.interfaces.nsIInputStream);
return mimeStream.QueryInterface(Ci.nsIInputStream);
}
function readFromClipboard()
{
var url;

Просмотреть файл

@ -22,6 +22,7 @@
# Ben Goodger <beng@google.com> (Original author)
# Gavin Sharp <gavin@gavinsharp.com>
# Pamela Greene <pamg.bugs@gmail.com>
# Ryan Flint <rflint@dslr.net>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
@ -150,12 +151,79 @@ var gEngineManagerDialog = {
document.getElementById("engineList").focus();
},
editKeyword: function engineManager_editKeyword() {
var selectedEngine = gEngineView.selectedEngine;
if (!selectedEngine)
return;
var prompt = Cc["@mozilla.org/embedcomp/prompt-service;1"].
getService(Ci.nsIPromptService);
var alias = { value: selectedEngine.alias };
var strings = document.getElementById("engineManagerBundle");
var title = strings.getString("editTitle");
var msg = strings.getFormattedString("editMsg", [selectedEngine.name]);
while (prompt.prompt(window, title, msg, alias, null, { })) {
var searchService = Cc["@mozilla.org/browser/search-service;1"].
getService(Ci.nsIBrowserSearchService);
var engine = searchService.getEngineByAlias(alias.value);
var bduplicate = false;
var eduplicate = false;
if (engine) {
if (engine.name != selectedEngine.name)
eduplicate = true;
} else {
try {
#ifdef MOZ_PLACES_BOOKMARKS
var bmserv = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
if (bmserv.getURIForKeyword(alias.value))
bduplicate = true;
#else
var bmserv = Cc["@mozilla.org/browser/bookmarks-service;1"].
getService(Ci.nsIBookmarksService);
if (bmserv.resolveKeyword(alias.value, {}))
bduplicate = true;
#endif
} catch(ex) {}
// Check for duplicates in changes we haven't committed yet
var engines = gEngineView._engineStore.engines;
for each (var engine in engines) {
if (engine.alias == alias.value &&
engine.name != selectedEngine.name) {
eduplicate = true;
break;
}
}
}
// Notify the user if they have chosen an existing engine/bookmark keyword
if (eduplicate || bduplicate) {
var dtitle = strings.getString("duplicateTitle");
var bookmark = strings.getString("duplicateBookmark");
var dmsg = strings.getFormattedString("duplicateMsg",
[(bduplicate) ? bookmark : '"' +
engine.name + '"']);
prompt.alert(window, dtitle, dmsg);
} else {
gEngineView._engineStore.changeEngine(selectedEngine, "alias",
alias.value);
gEngineView.invalidate();
break;
}
}
},
onSelect: function engineManager_onSelect() {
// buttons only work if an engine is selected and it's not the last engine
var disableButtons = (gEngineView.selectedIndex == -1) ||
(gEngineView.lastIndex == 0);
var lastSelected = (gEngineView.selectedIndex == gEngineView.lastIndex);
var firstSelected = (gEngineView.selectedIndex == 0);
var noSelection = (gEngineView.selectedIndex == -1);
document.getElementById("cmd_remove").setAttribute("disabled",
disableButtons);
@ -165,6 +233,8 @@ var gEngineManagerDialog = {
document.getElementById("cmd_movedown").setAttribute("disabled",
disableButtons || lastSelected);
document.getElementById("cmd_editkeyword").setAttribute("disabled",
noSelection);
}
};
@ -233,6 +303,23 @@ EngineUnhideOp.prototype = {
}
}
function EngineChangeOp(aEngineClone, aProp, aValue) {
if (!aEngineClone)
throw new Error("bad args to new EngineChangeOp!");
this._engine = aEngineClone.originalEngine;
this._prop = aProp;
this._newValue = aValue;
}
EngineChangeOp.prototype = {
_engine: null,
_prop: null,
_newValue: null,
commit: function ECO_commit() {
this._engine[this._prop] = this._newValue;
}
}
function EngineStore() {
var searchService = Cc["@mozilla.org/browser/search-service;1"].
getService(Ci.nsIBrowserSearchService);
@ -349,6 +436,15 @@ EngineStore.prototype = {
return added;
},
changeEngine: function ES_changeEngine(aEngine, aProp, aNewValue) {
var index = this._getIndexForEngine(aEngine);
if (index == -1)
throw new Error("invalid engine?");
this._engines[index][aProp] = aNewValue;
this._ops.push(new EngineChangeOp(aEngine, aProp, aNewValue));
},
reloadIcons: function ES_reloadIcons() {
this._engines.forEach(function (e) {
e.uri = e.originalEngine.uri;
@ -431,6 +527,8 @@ EngineView.prototype = {
getCellText: function(index, column) {
if (column.id == "engineName")
return this._engineStore.engines[index].name;
else if (column.id == "engineKeyword")
return this._engineStore.engines[index].alias;
return "";
},

Просмотреть файл

@ -71,8 +71,8 @@
<command id="cmd_movedown"
oncommand="gEngineManagerDialog.bump(-1);"
disabled="true"/>
<command id="cmd_editalias"
oncommand="gEngineManagerDialog.editAlias();"
<command id="cmd_editkeyword"
oncommand="gEngineManagerDialog.editKeyword();"
disabled="true"/>
</commandset>
@ -80,6 +80,10 @@
<key id="delete" keycode="VK_DELETE" command="cmd_remove"/>
</keyset>
<stringbundleset id="engineManagerBundleset">
<stringbundle id="engineManagerBundle" src="chrome://browser/locale/engineManager.properties"/>
</stringbundleset>
<description>&engineManager.intro;</description>
<separator class="thin"/>
<hbox flex="1">
@ -88,11 +92,16 @@
<treechildren id="engineChildren" flex="1"
ondraggesture="nsDragAndDrop.startDrag(event, gDragObserver);"/>
<treecols>
<treecol id="engineName" flex="1" hideheader="true"/>
<treecol id="engineName" flex="4" label="&columnLabel.name;"/>
<treecol id="engineKeyword" flex="1" label="&columnLabel.keyword;"/>
</treecols>
</tree>
<vbox>
<spacer flex="1"/>
<button id="edit"
label="&edit.label;"
accesskey="&edit.accesskey;"
command="cmd_editkeyword"/>
<button id="up"
label="&up.label;"
accesskey="&up.accesskey;"

Просмотреть файл

@ -2725,8 +2725,10 @@ SearchService.prototype = {
this._currentEngine = null;
if (engineToRemove._readOnly) {
// Just hide it (the "hidden" setter will notify)
// Just hide it (the "hidden" setter will notify) and remove its alias to
// avoid future conflicts with other engines.
engineToRemove.hidden = true;
engineToRemove.alias = null;
} else {
// Remove the engine file from disk (this might throw)
engineToRemove._remove();

Просмотреть файл

@ -2,6 +2,9 @@
<!ENTITY engineManager.style "min-width: 35em;">
<!ENTITY engineManager.intro "You have the following search engines installed:">
<!ENTITY columnLabel.name "Name">
<!ENTITY columnLabel.keyword "Keyword">
<!-- Buttons -->
<!ENTITY up.label "Move Up">
<!ENTITY up.accesskey "U">
@ -9,6 +12,8 @@
<!ENTITY dn.accesskey "D">
<!ENTITY remove.label "Remove">
<!ENTITY remove.accesskey "R">
<!ENTITY edit.label "Edit Keyword...">
<!ENTITY edit.accesskey "t">
<!ENTITY addEngine.label "Get more search engines...">
<!ENTITY addEngine.accesskey "A">

Просмотреть файл

@ -0,0 +1,8 @@
editTitle=Edit Keyword
editMsg=Enter a new keyword for "%S":
duplicateTitle=Duplicate Keyword
# Localization Note: The substitution in duplicateMsg will either be a search
# plugin name (e.g. ...in use by "Google".) or the duplicateBookmark string
# below (e.g. ...in use by a bookmark.).
duplicateMsg=You have chosen a keyword that is currently in use by %S. Please select another.
duplicateBookmark=a bookmark