Merge fx-team to central, a=merge CLOSED TREE

This commit is contained in:
Wes Kocher 2015-09-23 13:22:10 -07:00
commit 46c7f8fbad
50 changed files with 243 additions and 940 deletions

View File

@ -275,7 +275,7 @@ var gTests = [
Services.obs.removeObserver(searchObserver, "browser-search-engine-modified");
});
Services.search.addEngine("http://test:80/browser/browser/base/content/test/general/POSTSearchEngine.xml",
Ci.nsISearchEngine.DATA_XML, null, false);
null, null, false);
return deferred.promise;
}
},
@ -659,7 +659,7 @@ function promiseNewEngine(basename) {
info("Waiting for engine to be added: " + basename);
let addDeferred = Promise.defer();
let url = getRootDirectory(gTestPath) + basename;
Services.search.addEngine(url, Ci.nsISearchEngine.TYPE_MOZSEARCH, "", false, {
Services.search.addEngine(url, null, "", false, {
onSuccess: function (engine) {
info("Search engine added: " + basename);
registerCleanupFunction(() => {

View File

@ -194,32 +194,32 @@ add_task(function* cycleSuggestions() {
shiftKey: true,
accelKey: true,
};
let state = yield msg("key", { key: "VK_DOWN", modifiers: modifiers });
checkState(state, "xfoo", ["xfoo", "xbar"], 0, aSelectedButtonIndex);
state = yield msg("key", { key: "VK_DOWN", modifiers: modifiers });
checkState(state, "xbar", ["xfoo", "xbar"], 1, aSelectedButtonIndex);
state = yield msg("key", { key: "VK_DOWN", modifiers: modifiers });
checkState(state, "x", ["xfoo", "xbar"], -1, aSelectedButtonIndex);
state = yield msg("key", { key: "VK_DOWN", modifiers: modifiers });
checkState(state, "xfoo", ["xfoo", "xbar"], 0, aSelectedButtonIndex);
state = yield msg("key", { key: "VK_UP", modifiers: modifiers });
checkState(state, "x", ["xfoo", "xbar"], -1, aSelectedButtonIndex);
state = yield msg("key", { key: "VK_UP", modifiers: modifiers });
checkState(state, "xbar", ["xfoo", "xbar"], 1, aSelectedButtonIndex);
state = yield msg("key", { key: "VK_UP", modifiers: modifiers });
checkState(state, "xfoo", ["xfoo", "xbar"], 0, aSelectedButtonIndex);
state = yield msg("key", { key: "VK_UP", modifiers: modifiers });
checkState(state, "x", ["xfoo", "xbar"], -1, aSelectedButtonIndex);
});
yield cycle();
// Repeat with a one-off selected.
@ -689,7 +689,7 @@ function checkState(actualState, expectedInputVal, expectedSuggestions,
if (expectedSelectedIdx == -1 && expectedSelectedButtonIdx != undefined) {
expectedSelectedIdx = expectedSuggestions.length + expectedSelectedButtonIdx;
}
let expectedState = {
selectedIndex: expectedSelectedIdx,
numSuggestions: expectedSuggestions.length,
@ -759,34 +759,15 @@ function setUpEngines() {
let currentEngineName = Services.search.currentEngine.name;
let currentEngines = Services.search.getVisibleEngines();
info("Adding test search engines");
let engine1 = yield promiseNewEngine(TEST_ENGINE_BASENAME);
let engine2 = yield promiseNewEngine(TEST_ENGINE_2_BASENAME);
let engine1 = yield promiseNewSearchEngine(TEST_ENGINE_BASENAME);
let engine2 = yield promiseNewSearchEngine(TEST_ENGINE_2_BASENAME);
Services.search.currentEngine = engine1;
for (let engine of currentEngines) {
Services.search.removeEngine(engine);
}
registerCleanupFunction(() => {
Services.search.restoreDefaultEngines();
Services.search.removeEngine(engine1);
Services.search.removeEngine(engine2);
Services.search.currentEngine = Services.search.getEngineByName(currentEngineName);
});
});
}
function promiseNewEngine(basename) {
info("Waiting for engine to be added: " + basename);
let addDeferred = Promise.defer();
let url = getRootDirectory(gTestPath) + basename;
Services.search.addEngine(url, Ci.nsISearchEngine.TYPE_MOZSEARCH, "", false, {
onSuccess: function (engine) {
info("Search engine added: " + basename);
addDeferred.resolve(engine);
},
onError: function (errCode) {
ok(false, "addEngine failed with error code " + errCode);
addDeferred.reject();
},
});
return addDeferred.promise;
}

View File

@ -50,7 +50,7 @@ function test() {
});
Services.search.addEngine("http://test:80/browser/browser/base/content/test/general/POSTSearchEngine.xml",
Ci.nsISearchEngine.DATA_XML, null, false);
null, null, false);
}
var gCurrTest;

View File

@ -65,6 +65,76 @@ function once(target, name) {
});
}
function fetchFile(uri) {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.open("GET", uri, true);
xhr.onreadystatechange = function() {
if (this.readyState != this.DONE) {
return;
}
try {
resolve(this.responseText);
} catch (ex) {
ok(false, `Script error reading ${uri}: ${ex}`);
resolve("");
}
};
xhr.onerror = error => {
ok(false, `XHR error reading ${uri}: ${error}`);
resolve("");
};
xhr.send(null);
});
}
var gChromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"]
.getService(Ci.nsIChromeRegistry);
var gChromeMap = new Map();
function getBaseUriForChromeUri(chromeUri) {
let chromeFile = chromeUri + "gobbledygooknonexistentfile.reallynothere";
let uri = Services.io.newURI(chromeFile, null, null);
let fileUri = gChromeReg.convertChromeURL(uri);
return fileUri.resolve(".");
}
function parseManifest(manifestUri) {
return fetchFile(manifestUri.spec).then(data => {
for (let line of data.split('\n')) {
let [type, ...argv] = line.split(/\s+/);
let component;
if (type == "content" || type == "skin") {
[component] = argv;
} else {
// skip unrelated lines
continue;
}
let chromeUri = `chrome://${component}/${type}/`;
gChromeMap.set(getBaseUriForChromeUri(chromeUri), chromeUri);
}
});
}
function convertToChromeUri(fileUri) {
let baseUri = fileUri.spec;
let path = "";
while (true) {
let slashPos = baseUri.lastIndexOf("/", baseUri.length - 2);
if (slashPos < 0) {
info(`File not accessible from chrome protocol: ${fileUri.path}`);
return fileUri;
}
path = baseUri.slice(slashPos + 1) + path;
baseUri = baseUri.slice(0, slashPos + 1);
if (gChromeMap.has(baseUri)) {
let chromeBaseUri = gChromeMap.get(baseUri);
let chromeUri = `${chromeBaseUri}${path}`;
return Services.io.newURI(chromeUri, null, null);
}
}
}
function messageIsCSSError(msg, innerWindowID, outerWindowID) {
// Only care about CSS errors generated by our iframe:
if ((msg instanceof Ci.nsIScriptError) &&
@ -85,15 +155,11 @@ add_task(function checkAllTheCSS() {
// This asynchronously produces a list of URLs (sadly, mostly sync on our
// test infrastructure because it runs against jarfiles there, and
// our zipreader APIs are all sync)
let uris = yield generateURIsFromDirTree(appDir, ".css");
let uris = yield generateURIsFromDirTree(appDir, [".css", ".manifest"]);
// Create a clean iframe to load all the files into. This needs to live at a
// file or jar URI (depending on whether we're using a packaged build or not)
// so that it's allowed to load other same-scheme URIs (i.e. the browser css).
let resHandler = Services.io.getProtocolHandler("resource")
.QueryInterface(Ci.nsISubstitutingProtocolHandler);
let resURI = Services.io.newURI('resource://testing-common/resource_test_file.html', null, null);
let testFile = resHandler.resolveURI(resURI);
// chrome URI so that it's allowed to load and parse any styles.
let testFile = getRootDirectory(gTestPath) + "dummy_page.html";
let windowless = Services.appShell.createWindowlessBrowser();
let iframe = windowless.document.createElementNS("http://www.w3.org/1999/xhtml", "html:iframe");
windowless.document.documentElement.appendChild(iframe);
@ -106,6 +172,20 @@ add_task(function checkAllTheCSS() {
let innerWindowID = windowUtils.currentInnerWindowID;
let outerWindowID = windowUtils.outerWindowID;
// Parse and remove all manifests from the list.
// NOTE that this must be done before filtering out devtools paths
// so that all chrome paths can be recorded.
let manifestPromises = [];
uris = uris.filter(uri => {
if (uri.path.endsWith(".manifest")) {
manifestPromises.push(parseManifest(uri));
return false;
}
return true;
});
// Wait for all manifest to be parsed
yield Promise.all(manifestPromises);
// We build a list of promises that get resolved when their respective
// files have loaded and produced no errors.
let allPromises = [];
@ -133,7 +213,8 @@ add_task(function checkAllTheCSS() {
linkEl.addEventListener("load", onLoad);
linkEl.addEventListener("error", onError);
linkEl.setAttribute("type", "text/css");
linkEl.setAttribute("href", uri.spec);
let chromeUri = convertToChromeUri(uri);
linkEl.setAttribute("href", chromeUri.spec);
allPromises.push(promiseForThisSpec.promise);
doc.head.appendChild(linkEl);
}

View File

@ -1033,8 +1033,7 @@ function promiseNewSearchEngine(basename) {
return new Promise((resolve, reject) => {
info("Waiting for engine to be added: " + basename);
let url = getRootDirectory(gTestPath) + basename;
Services.search.addEngine(url, Ci.nsISearchEngine.TYPE_MOZSEARCH, "",
false, {
Services.search.addEngine(url, null, "", false, {
onSuccess: function (engine) {
info("Search engine added: " + basename);
registerCleanupFunction(() => Services.search.removeEngine(engine));

View File

@ -237,7 +237,7 @@ function promiseNewSearchEngine({name: basename, numLogos}) {
// Wait for addEngine().
let addDeferred = Promise.defer();
let url = getRootDirectory(gTestPath) + basename;
Services.search.addEngine(url, Ci.nsISearchEngine.TYPE_MOZSEARCH, "", false, {
Services.search.addEngine(url, null, "", false, {
onSuccess: function (engine) {
info("Search engine added: " + basename);
gNewEngines.push(engine);

View File

@ -930,6 +930,10 @@ loop.OTSdkDriver = (function() {
this.dispatcher.dispatch(new sharedActions.ConnectionFailure({
reason: FAILURE_DETAILS.UNABLE_TO_PUBLISH_MEDIA
}));
} else if (event.code === OT.ExceptionCodes.UNABLE_TO_PUBLISH) {
// We need to log the message so that we can understand where the exception
// is coming from. Potentially a temporary addition.
this._notifyMetricsEvent("sdk.exception." + event.code + "." + event.message);
} else {
this._notifyMetricsEvent("sdk.exception." + event.code);
}

View File

@ -1537,6 +1537,26 @@ describe("loop.OTSdkDriver", function () {
}));
});
describe("Unable to publish (not GetUserMedia)", function() {
it("should notify metrics", function() {
sdk.trigger("exception", {
code: OT.ExceptionCodes.UNABLE_TO_PUBLISH,
message: "Fake",
title: "Connect Failed"
});
sinon.assert.calledOnce(dispatcher.dispatch);
sinon.assert.calledWithExactly(dispatcher.dispatch,
new sharedActions.ConnectionStatus({
event: "sdk.exception." + OT.ExceptionCodes.UNABLE_TO_PUBLISH + ".Fake",
state: "starting",
connections: 0,
sendStreams: 0,
recvStreams: 0
}));
});
});
describe("Unable to publish (GetUserMedia)", function() {
it("should destroy the publisher", function() {
sdk.trigger("exception", {

View File

@ -446,13 +446,11 @@
if (target.engine) {
this.currentEngine = target.engine;
} else if (target.classList.contains("addengine-item")) {
// We only detect OpenSearch files
var type = Ci.nsISearchEngine.DATA_XML;
// Select the installed engine if the installation succeeds
var installCallback = {
onSuccess: engine => this.currentEngine = engine
}
Services.search.addEngine(target.getAttribute("uri"), type,
Services.search.addEngine(target.getAttribute("uri"), null,
target.getAttribute("src"), false,
installCallback);
}
@ -1432,8 +1430,7 @@
Components.utils.reportError("Error adding search engine: " + errorCode);
}
}
Services.search.addEngine(target.getAttribute("uri"),
Ci.nsISearchEngine.DATA_XML,
Services.search.addEngine(target.getAttribute("uri"), null,
target.getAttribute("image"), false,
installCallback);
}

View File

@ -7,7 +7,6 @@ support-files =
head.js
opensearch.html
test.html
testEngine.src
testEngine.xml
testEngine_diacritics.xml
testEngine_dupe.xml

View File

@ -99,8 +99,7 @@ function* promiseSetEngine() {
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
ss.addEngine("http://mochi.test:8888/browser/browser/components/search/test/426329.xml",
Ci.nsISearchEngine.DATA_XML, "data:image/x-icon,%00",
false);
null, "data:image/x-icon,%00", false);
return deferred.promise;
}

View File

@ -24,8 +24,7 @@ function test() {
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/483086-1.xml",
Ci.nsISearchEngine.DATA_XML, "data:image/x-icon;%00",
false);
null, "data:image/x-icon;%00", false);
}
function test2() {
@ -37,7 +36,7 @@ function test2() {
is(engine.searchForm, "http://example.com", "SearchForm is correct");
gSS.removeEngine(engine);
break;
case "engine-removed":
case "engine-removed":
Services.obs.removeObserver(observer, "browser-search-engine-modified");
finish();
break;
@ -46,6 +45,5 @@ function test2() {
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/483086-2.xml",
Ci.nsISearchEngine.DATA_XML, "data:image/x-icon;%00",
false);
null, "data:image/x-icon;%00", false);
}

View File

@ -44,12 +44,11 @@ var gTests = [
name: "Foo",
alias: null,
description: "Foo Search",
searchForm: "http://mochi.test:8888/browser/browser/components/search/test/",
type: Ci.nsISearchEngine.TYPE_OPENSEARCH
searchForm: "http://mochi.test:8888/browser/browser/components/search/test/"
},
run: function () {
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.xml",
Ci.nsISearchEngine.DATA_XML, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
null, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
false);
},
added: function (engine) {
@ -77,37 +76,6 @@ var gTests = [
ok(currentEngine, "An engine is present.");
isnot(currentEngine.name, this.engine.name, "Current engine reset after removal");
nextTest();
}
},
{
name: "sherlock install",
engine: {
name: "Test Sherlock",
alias: null,
description: "Test Description",
searchForm: "http://example.com/searchform",
type: Ci.nsISearchEngine.TYPE_SHERLOCK
},
run: function () {
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.src",
Ci.nsISearchEngine.DATA_TEXT, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
false);
},
added: function (engine) {
ok(engine, "engine was added.");
checkEngine(this.engine, engine);
let engineFromSS = gSS.getEngineByName(this.engine.name);
is(engineFromSS, engine, "engine is obtainable via getEngineByName");
gSS.removeEngine(engine);
},
removed: function (engine) {
let currentEngine = gSS.currentEngine;
ok(currentEngine, "An engine is present.");
isnot(currentEngine.name, this.engine.name, "Current engine reset after removal");
nextTest();
}
}

View File

@ -30,7 +30,6 @@ function test() {
alias: null,
description: "Amazon.com Search",
searchForm: "https://www.amazon.com/exec/obidos/external-search/?field-keywords=&mode=blended&tag=mozilla-20&sourceid=Mozilla-search",
type: Ci.nsISearchEngine.TYPE_MOZSEARCH,
hidden: false,
wrappedJSObject: {
queryCharset: "UTF-8",

View File

@ -40,7 +40,6 @@ function test() {
alias: null,
description: "Bing. Search by Microsoft.",
searchForm: "https://www.bing.com/search?q=&pc=MOZI",
type: Ci.nsISearchEngine.TYPE_MOZSEARCH,
hidden: false,
wrappedJSObject: {
queryCharset: "UTF-8",

View File

@ -31,8 +31,7 @@ function test() {
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
ss.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine_mozsearch.xml",
Ci.nsISearchEngine.DATA_XML, "data:image/x-icon,%00",
false);
null, "data:image/x-icon,%00", false);
function startTest() {
contextMenu = document.getElementById("contentAreaContextMenu");

View File

@ -30,7 +30,6 @@ function test() {
alias: null,
description: "eBay - Online auctions",
searchForm: "http://search.ebay.com/",
type: Ci.nsISearchEngine.TYPE_MOZSEARCH,
hidden: false,
wrappedJSObject: {
queryCharset: "ISO-8859-1",

View File

@ -46,7 +46,6 @@ function test() {
alias: null,
description: "Google Search",
searchForm: "https://www.google.com/search?q=&ie=utf-8&oe=utf-8",
type: Ci.nsISearchEngine.TYPE_MOZSEARCH,
hidden: false,
wrappedJSObject: {
queryCharset: "UTF-8",

View File

@ -96,9 +96,7 @@ function test() {
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
Services.search.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.xml",
Ci.nsISearchEngine.DATA_XML,
"data:image/x-icon,%00",
false);
null, "data:image/x-icon,%00", false);
}

View File

@ -9,7 +9,7 @@ function promiseNewEngine(basename) {
Services.search.init({
onInitComplete: function() {
let url = getRootDirectory(gTestPath) + basename;
Services.search.addEngine(url, Ci.nsISearchEngine.TYPE_MOZSEARCH, "", false, {
Services.search.addEngine(url, null, "", false, {
onSuccess: function (engine) {
info("Search engine added: " + basename);
resolve(engine);

View File

@ -51,8 +51,7 @@ function test() {
ok(false, "failed to install engine: " + errorCode);
}
};
Services.search.addEngine(engineURL + "426329.xml",
Ci.nsISearchEngine.DATA_XML,
Services.search.addEngine(engineURL + "426329.xml", null,
"data:image/x-icon,%00", false, installCallback);
}

View File

@ -8,11 +8,7 @@ function getString(key, ...params) {
}
function AddSearchProvider(...args) {
return gBrowser.addTab(ROOT + "webapi.html?AddSearchProvider:" + encodeURIComponent(JSON.stringify(args)));
}
function addSearchEngine(...args) {
return gBrowser.addTab(ROOT + "webapi.html?addSearchEngine:" + encodeURIComponent(JSON.stringify(args)));
return gBrowser.addTab(ROOT + "webapi.html?" + encodeURIComponent(JSON.stringify(args)));
}
function promiseDialogOpened() {
@ -34,7 +30,7 @@ function promiseDialogOpened() {
});
}
add_task(function* test_working_AddSearchProvider() {
add_task(function* test_working() {
gBrowser.selectedTab = AddSearchProvider(ROOT + "testEngine.xml");
let dialog = yield promiseDialogOpened();
@ -46,7 +42,7 @@ add_task(function* test_working_AddSearchProvider() {
gBrowser.removeCurrentTab();
});
add_task(function* test_HTTP_AddSearchProvider() {
add_task(function* test_HTTP() {
gBrowser.selectedTab = AddSearchProvider(ROOT.replace("http:", "HTTP:") + "testEngine.xml");
let dialog = yield promiseDialogOpened();
@ -58,7 +54,7 @@ add_task(function* test_HTTP_AddSearchProvider() {
gBrowser.removeCurrentTab();
});
add_task(function* test_relative_AddSearchProvider() {
add_task(function* test_relative() {
gBrowser.selectedTab = AddSearchProvider("testEngine.xml");
let dialog = yield promiseDialogOpened();
@ -70,7 +66,7 @@ add_task(function* test_relative_AddSearchProvider() {
gBrowser.removeCurrentTab();
});
add_task(function* test_invalid_AddSearchProvider() {
add_task(function* test_invalid() {
gBrowser.selectedTab = AddSearchProvider("z://foobar");
let dialog = yield promiseDialogOpened();
@ -82,7 +78,7 @@ add_task(function* test_invalid_AddSearchProvider() {
gBrowser.removeCurrentTab();
});
add_task(function* test_missing_AddSearchProvider() {
add_task(function* test_missing() {
let url = ROOT + "foobar.xml";
gBrowser.selectedTab = AddSearchProvider(url);
@ -94,88 +90,3 @@ add_task(function* test_missing_AddSearchProvider() {
gBrowser.removeCurrentTab();
});
add_task(function* test_working_addSearchEngine_xml() {
gBrowser.selectedTab = addSearchEngine(ROOT + "testEngine.xml", "", "", "");
let dialog = yield promiseDialogOpened();
is(dialog.args.promptType, "confirmEx", "Should see the confirmation dialog.");
is(dialog.args.text, getString("addEngineConfirmation", "Foo", "example.com"),
"Should have seen the right install message");
dialog.document.documentElement.cancelDialog();
gBrowser.removeCurrentTab();
});
add_task(function* test_working_addSearchEngine_src() {
gBrowser.selectedTab = addSearchEngine(ROOT + "testEngine.src", "", "", "");
let dialog = yield promiseDialogOpened();
is(dialog.args.promptType, "confirmEx", "Should see the confirmation dialog.");
is(dialog.args.text, getString("addEngineConfirmation", "Test Sherlock", "example.com"),
"Should have seen the right install message");
dialog.document.documentElement.cancelDialog();
gBrowser.removeCurrentTab();
});
add_task(function* test_relative_addSearchEngine_xml() {
gBrowser.selectedTab = addSearchEngine("testEngine.xml", "", "", "");
let dialog = yield promiseDialogOpened();
is(dialog.args.promptType, "confirmEx", "Should see the confirmation dialog.");
is(dialog.args.text, getString("addEngineConfirmation", "Foo", "example.com"),
"Should have seen the right install message");
dialog.document.documentElement.cancelDialog();
gBrowser.removeCurrentTab();
});
add_task(function* test_relative_addSearchEngine_src() {
gBrowser.selectedTab = addSearchEngine("testEngine.src", "", "", "");
let dialog = yield promiseDialogOpened();
is(dialog.args.promptType, "confirmEx", "Should see the confirmation dialog.");
is(dialog.args.text, getString("addEngineConfirmation", "Test Sherlock", "example.com"),
"Should have seen the right install message");
dialog.document.documentElement.cancelDialog();
gBrowser.removeCurrentTab();
});
add_task(function* test_invalid_addSearchEngine() {
gBrowser.selectedTab = addSearchEngine("z://foobar", "", "", "");
let dialog = yield promiseDialogOpened();
is(dialog.args.promptType, "alert", "Should see the alert dialog.");
is(dialog.args.text, getString("error_invalid_engine_msg", brandName),
"Should have seen the right error message")
dialog.document.documentElement.acceptDialog();
gBrowser.removeCurrentTab();
});
add_task(function* test_invalid_icon_addSearchEngine() {
gBrowser.selectedTab = addSearchEngine(ROOT + "testEngine.src", "z://foobar", "", "");
let dialog = yield promiseDialogOpened();
is(dialog.args.promptType, "alert", "Should see the alert dialog.");
is(dialog.args.text, getString("error_invalid_engine_msg", brandName),
"Should have seen the right error message")
dialog.document.documentElement.acceptDialog();
gBrowser.removeCurrentTab();
});
add_task(function* test_missing_addSearchEngine() {
let url = ROOT + "foobar.xml";
gBrowser.selectedTab = addSearchEngine(url, "", "", "");
let dialog = yield promiseDialogOpened();
is(dialog.args.promptType, "alert", "Should see the alert dialog.");
is(dialog.args.text, getString("error_loading_engine_msg2", brandName, url),
"Should have seen the right error message")
dialog.document.documentElement.acceptDialog();
gBrowser.removeCurrentTab();
});

View File

@ -30,7 +30,6 @@ function test() {
alias: null,
description: "Yahoo Search",
searchForm: "https://search.yahoo.com/yhs/search?p=&ei=UTF-8&hspart=mozilla",
type: Ci.nsISearchEngine.TYPE_MOZSEARCH,
hidden: false,
wrappedJSObject: {
queryCharset: "UTF-8",

View File

@ -146,7 +146,7 @@ function promiseNewEngine(basename, options = {}) {
onInitComplete: function() {
let url = getRootDirectory(gTestPath) + basename;
let current = Services.search.currentEngine;
Services.search.addEngine(url, Ci.nsISearchEngine.TYPE_MOZSEARCH, "", false, {
Services.search.addEngine(url, null, "", false, {
onSuccess: function (engine) {
info("Search engine added: " + basename);
if (setAsCurrent) {

View File

@ -1,11 +0,0 @@
<search
name="Test Sherlock"
description="Test Description"
method="GET"
searchform="http://example.com/searchform"
action="http://example.com/action"
queryCharset="UTF-8"
>
<input name="userParam" user>
<input name="param" value="value">
</search>

View File

@ -4,14 +4,10 @@
<head>
<script>
function installEngine() {
var query = window.location.search.substring(1).split(":");
var func = query[0];
var args = JSON.parse(decodeURIComponent(query[1]));
var query = window.location.search.substring(1);
var args = JSON.parse(decodeURIComponent(query));
if (func == "AddSearchProvider")
window.external.AddSearchProvider(...args);
else if (func == "addSearchEngine")
window.sidebar.addSearchEngine(...args);
window.external.AddSearchProvider(...args);
}
</script>
</head>

View File

@ -317,7 +317,7 @@ function waitForNewEngine(basename, numImages) {
// Wait for addEngine().
let addDeferred = Promise.defer();
let url = getRootDirectory(gTestPath) + basename;
Services.search.addEngine(url, Ci.nsISearchEngine.TYPE_MOZSEARCH, "", false, {
Services.search.addEngine(url, null, "", false, {
onSuccess: function (engine) {
info("Search engine added: " + basename);
addDeferred.resolve(engine);

View File

@ -3,7 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@import url("chrome://devtools/skin/themes/floating-scrollbars.css");
@import url("floating-scrollbars.css");
scrollbar thumb {
background-color: rgba(170,170,170,0.2) !important;

View File

@ -46,3 +46,7 @@ property FillOpacity
// Push API
method PushManager.subscribe
method PushSubscription.unsubscribe
// window.sidebar.addSearchEngine
attribute Window.sidebar
method External.addSearchEngine

View File

@ -13,6 +13,7 @@ interface External
// Mozilla extension
partial interface External {
[UnsafeInPrerendering] void addSearchEngine(DOMString engineURL, DOMString iconURL,
DOMString suggestedTitle, DOMString suggestedCategory);
[UnsafeInPrerendering, UseCounter]
void addSearchEngine(DOMString engineURL, DOMString iconURL,
DOMString suggestedTitle, DOMString suggestedCategory);
};

View File

@ -407,7 +407,7 @@ partial interface Window {
#ifdef HAVE_SIDEBAR
// Mozilla extension
partial interface Window {
[Replaceable, Throws]
[Replaceable, Throws, UseCounter]
readonly attribute (External or WindowProxy) sidebar;
};
#endif

View File

@ -271,9 +271,9 @@ class TabsGridLayout extends GridView
post(new Runnable() {
@Override
public void run() {
final int displayCount = getChildCount();
final int displayCount = tabsAdapter.getCount();
for (int i = getFirstVisiblePosition(); i <= getLastVisiblePosition(); i++) {
for (int i = 0; i < displayCount; i++) {
final Tab tab = tabsAdapter.getItem(i);
final boolean checked = displayCount == 1 || i == selected;
final View tabView = getViewForTab(tab);

View File

@ -4775,7 +4775,7 @@ pref("urlclassifier.disallow_completions", "test-malware-simple,test-phish-simpl
pref("urlclassifier.trackingTable", "test-track-simple,mozstd-track-digest256");
pref("urlclassifier.trackingWhitelistTable", "test-trackwhite-simple,mozstd-trackwhite-digest256");
pref("browser.safebrowsing.provider.mozilla.lists", "mozstd-track-digest256,mozstd-trackwhite-digest256");
pref("browser.safebrowsing.provider.mozilla.lists", "mozstd-track-digest256,mozstd-trackwhite-digest256,mozfull-track-digest256");
pref("browser.safebrowsing.provider.mozilla.updateURL", "https://shavar.services.mozilla.com/downloads?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
pref("browser.safebrowsing.provider.mozilla.gethashURL", "https://shavar.services.mozilla.com/gethash?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
// Block lists for tracking protection. The name values will be used as the keys

View File

@ -22,7 +22,7 @@ interface nsISearchSubmission : nsISupports
readonly attribute nsIURI uri;
};
[scriptable, uuid(65fd517b-6bda-4bac-bbe1-42de1b3a7df6)]
[scriptable, uuid(620bd920-0491-48c8-99a8-d6047e64802d)]
interface nsISearchEngine : nsISupports
{
/**
@ -115,19 +115,6 @@ interface nsISearchEngine : nsISupports
*/
void speculativeConnect(in jsval options);
/**
* Supported search engine types.
*/
const unsigned long TYPE_MOZSEARCH = 1;
const unsigned long TYPE_SHERLOCK = 2;
const unsigned long TYPE_OPENSEARCH = 3;
/**
* Supported search engine data types.
*/
const unsigned long DATA_XML = 1;
const unsigned long DATA_TEXT = 2;
/**
* An optional shortcut alias for the engine.
* When non-null, this is a unique identifier.
@ -159,11 +146,6 @@ interface nsISearchEngine : nsISupports
*/
readonly attribute AString searchForm;
/**
* The search engine type.
*/
readonly attribute long type;
/**
* An optional unique identifier for this search engine within the context of
* the distribution, as provided by the distributing entity.
@ -296,8 +278,7 @@ interface nsIBrowserSearchService : nsISupports
* The URL to the search engine's description file.
*
* @param dataType
* An integer representing the plugin file format. Must be one
* of the supported search engine data types defined above.
* Obsolete, the value is ignored.
*
* @param iconURL
* A URL string to an icon file to be used as the search engine's
@ -315,8 +296,8 @@ interface nsIBrowserSearchService : nsISupports
* addition is complete, or if the addition fails. It will not be
* called if addEngine throws an exception.
*
* @throws NS_ERROR_FAILURE if the type is invalid, or if the description
* file cannot be successfully loaded.
* @throws NS_ERROR_FAILURE if the description file cannot be successfully
* loaded.
*/
void addEngine(in AString engineURL, in long dataType, in AString iconURL,
in boolean confirm, [optional] in nsISearchInstallCallback callback);

View File

@ -442,8 +442,7 @@ function* addTestEngine(basename, httpServer=undefined) {
}, "browser-search-engine-modified", false);
do_print("Adding engine from URL: " + dataUrl + basename);
Services.search.addEngine(dataUrl + basename,
Ci.nsISearchEngine.DATA_XML, null, false);
Services.search.addEngine(dataUrl + basename, null, null, false);
});
}

View File

@ -24,20 +24,15 @@ MainProcessSingleton.prototype = {
Services.obs.notifyObservers(logMsg, "console-api-log-event", null);
},
// Called when a webpage calls either window.external.AddSearchProvider or
// window.sidebar.addSearchEngine
addSearchEngine: function({ target: browser, data: { pageURL, engineURL, iconURL, type } }) {
// Called when a webpage calls window.external.AddSearchProvider
addSearchEngine: function({ target: browser, data: { pageURL, engineURL } }) {
pageURL = NetUtil.newURI(pageURL);
engineURL = NetUtil.newURI(engineURL, null, pageURL);
if (iconURL) {
iconURL = NetUtil.newURI(iconURL, null, pageURL);
}
else {
let tabbrowser = browser.getTabBrowser();
if (browser.mIconURL && (!tabbrowser || tabbrowser.shouldLoadFavIcon(pageURL)))
iconURL = NetUtil.newURI(browser.mIconURL);
}
let iconURL;
let tabbrowser = browser.getTabBrowser();
if (browser.mIconURL && (!tabbrowser || tabbrowser.shouldLoadFavIcon(pageURL)))
iconURL = NetUtil.newURI(browser.mIconURL);
try {
// Make sure the URLs are HTTP, HTTPS, or FTP.
@ -50,7 +45,7 @@ MainProcessSingleton.prototype = {
throw "Unsupported search icon URL: " + iconURL;
}
catch(ex) {
Cu.reportError("Invalid argument passed to window.sidebar.addSearchEngine: " + ex);
Cu.reportError("Invalid argument passed to window.external.AddSearchProvider: " + ex);
var searchBundle = Services.strings.createBundle("chrome://global/locale/search/search.properties");
var brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
@ -66,7 +61,7 @@ MainProcessSingleton.prototype = {
if (status != Cr.NS_OK)
return;
Services.search.addEngine(engineURL.spec, type, iconURL ? iconURL.spec : null, true);
Services.search.addEngine(engineURL.spec, null, iconURL ? iconURL.spec : null, true);
})
},

View File

@ -97,13 +97,6 @@ const SEARCH_SERVICE_METADATA_WRITTEN = "write-metadata-to-disk-complete";
*/
const SEARCH_SERVICE_CACHE_WRITTEN = "write-cache-to-disk-complete";
const SEARCH_TYPE_MOZSEARCH = Ci.nsISearchEngine.TYPE_MOZSEARCH;
const SEARCH_TYPE_OPENSEARCH = Ci.nsISearchEngine.TYPE_OPENSEARCH;
const SEARCH_TYPE_SHERLOCK = Ci.nsISearchEngine.TYPE_SHERLOCK;
const SEARCH_DATA_XML = Ci.nsISearchEngine.DATA_XML;
const SEARCH_DATA_TEXT = Ci.nsISearchEngine.DATA_TEXT;
// Delay for lazy serialization (ms)
const LAZY_SERIALIZE_DELAY = 100;
@ -220,12 +213,6 @@ const SEARCH_DEFAULT_UPDATE_INTERVAL = 7;
// from the server doesn't specify an interval.
const SEARCH_GEO_DEFAULT_UPDATE_INTERVAL = 2592000; // 30 days.
// Returns false for whitespace-only or commented out lines in a
// Sherlock file, true otherwise.
function isUsefulLine(aLine) {
return !(/^\s*($|#)/i.test(aLine));
}
this.__defineGetter__("FileUtils", function() {
delete this.FileUtils;
Components.utils.import("resource://gre/modules/FileUtils.jsm");
@ -873,29 +860,6 @@ function getVerificationHash(aName) {
return hasher.finish(true);
}
/**
* Used to verify a given DOM node's localName and namespaceURI.
* @param aElement
* The element to verify.
* @param aLocalNameArray
* An array of strings to compare against aElement's localName.
* @param aNameSpaceArray
* An array of strings to compare against aElement's namespaceURI.
*
* @returns false if aElement is null, or if its localName or namespaceURI
* does not match one of the elements in the aLocalNameArray or
* aNameSpaceArray arrays, respectively.
* @throws NS_ERROR_INVALID_ARG if aLocalNameArray or aNameSpaceArray are null.
*/
function checkNameSpace(aElement, aLocalNameArray, aNameSpaceArray) {
if (!aLocalNameArray || !aNameSpaceArray)
FAIL("missing aLocalNameArray or aNameSpaceArray for checkNameSpace");
return (aElement &&
(aLocalNameArray.indexOf(aElement.localName) != -1) &&
(aNameSpaceArray.indexOf(aElement.namespaceURI) != -1));
}
/**
* Safely close a nsISafeOutputStream.
* @param aFOS
@ -951,128 +915,6 @@ function getDir(aKey, aIFace) {
return Services.dirsvc.get(aKey, aIFace || Ci.nsIFile);
}
/**
* The following two functions are essentially copied from
* nsInternetSearchService. They are required for backwards compatibility.
*/
function queryCharsetFromCode(aCode) {
const codes = [];
codes[0] = "macintosh";
codes[6] = "x-mac-greek";
codes[35] = "x-mac-turkish";
codes[513] = "ISO-8859-1";
codes[514] = "ISO-8859-2";
codes[517] = "ISO-8859-5";
codes[518] = "ISO-8859-6";
codes[519] = "ISO-8859-7";
codes[520] = "ISO-8859-8";
codes[521] = "ISO-8859-9";
codes[1280] = "windows-1252";
codes[1281] = "windows-1250";
codes[1282] = "windows-1251";
codes[1283] = "windows-1253";
codes[1284] = "windows-1254";
codes[1285] = "windows-1255";
codes[1286] = "windows-1256";
codes[1584] = "GB2312";
codes[1585] = "gbk";
codes[1600] = "EUC-KR";
codes[2080] = "ISO-2022-JP";
codes[2096] = "ISO-2022-CN";
codes[2112] = "ISO-2022-KR";
codes[2336] = "EUC-JP";
codes[2352] = "GB2312";
codes[2353] = "x-euc-tw";
codes[2368] = "EUC-KR";
codes[2561] = "Shift_JIS";
codes[2562] = "KOI8-R";
codes[2563] = "Big5";
codes[2565] = "HZ-GB-2312";
if (codes[aCode])
return codes[aCode];
// Don't bother being fancy about what to return in the failure case.
return "windows-1252";
}
function fileCharsetFromCode(aCode) {
const codes = [
"macintosh", // 0
"Shift_JIS", // 1
"Big5", // 2
"EUC-KR", // 3
"X-MAC-ARABIC", // 4
"X-MAC-HEBREW", // 5
"X-MAC-GREEK", // 6
"X-MAC-CYRILLIC", // 7
"X-MAC-DEVANAGARI" , // 9
"X-MAC-GURMUKHI", // 10
"X-MAC-GUJARATI", // 11
"X-MAC-ORIYA", // 12
"X-MAC-BENGALI", // 13
"X-MAC-TAMIL", // 14
"X-MAC-TELUGU", // 15
"X-MAC-KANNADA", // 16
"X-MAC-MALAYALAM", // 17
"X-MAC-SINHALESE", // 18
"X-MAC-BURMESE", // 19
"X-MAC-KHMER", // 20
"X-MAC-THAI", // 21
"X-MAC-LAOTIAN", // 22
"X-MAC-GEORGIAN", // 23
"X-MAC-ARMENIAN", // 24
"GB2312", // 25
"X-MAC-TIBETAN", // 26
"X-MAC-MONGOLIAN", // 27
"X-MAC-ETHIOPIC", // 28
"X-MAC-CENTRALEURROMAN", // 29
"X-MAC-VIETNAMESE", // 30
"X-MAC-EXTARABIC" // 31
];
// Sherlock files have always defaulted to macintosh, so do that here too
return codes[aCode] || codes[0];
}
/**
* Returns a string interpretation of aBytes using aCharset, or null on
* failure.
*/
function bytesToString(aBytes, aCharset) {
var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
createInstance(Ci.nsIScriptableUnicodeConverter);
LOG("bytesToString: converting using charset: " + aCharset);
try {
converter.charset = aCharset;
return converter.convertFromByteArray(aBytes, aBytes.length);
} catch (ex) {}
return null;
}
/**
* Converts an array of bytes representing a Sherlock file into an array of
* lines representing the useful data from the file.
*
* @param aBytes
* The array of bytes representing the Sherlock file.
* @param aCharsetCode
* An integer value representing a character set code to be passed to
* fileCharsetFromCode, or null for the default Sherlock encoding.
*/
function sherlockBytesToLines(aBytes, aCharsetCode) {
// fileCharsetFromCode returns the default encoding if aCharsetCode is null
var charset = fileCharsetFromCode(aCharsetCode);
var dataString = bytesToString(aBytes, charset);
if (!dataString)
FAIL("sherlockBytesToLines: Couldn't convert byte array!", Cr.NS_ERROR_FAILURE);
// Split the string into lines, and filter out comments and
// whitespace-only lines
return dataString.split(NEW_LINES).filter(isUsefulLine);
}
/**
* Gets the current value of the locale. It's possible for this preference to
* be localized, so we have to do a little extra work here. Similar code
@ -1486,15 +1328,11 @@ EngineURL.prototype = {
* @param aLocation
* A nsILocalFile or nsIURI object representing the location of the
* search engine data file.
* @param aSourceDataType
* The data type of the file used to describe the engine. Must be either
* DATA_XML or DATA_TEXT.
* @param aIsReadOnly
* Boolean indicating whether the engine should be treated as read-only.
* Read only engines cannot be serialized to file.
*/
function Engine(aLocation, aSourceDataType, aIsReadOnly) {
this._dataType = aSourceDataType;
function Engine(aLocation, aIsReadOnly) {
this._readOnly = aIsReadOnly;
this._urls = [];
@ -1533,11 +1371,8 @@ Engine.prototype = {
// A distribution-unique identifier for the engine. Either null or set
// when loaded. See getter.
_identifier: undefined,
// The data describing the engine. Is either an array of bytes, for Sherlock
// files, or an XML document element, for XML plugins.
// The data describing the engine, in the form of an XML document element.
_data: null,
// The engine's data type. See data types (DATA_) defined above.
_dataType: null,
// Whether or not the engine is readonly.
_readOnly: true,
// The engine's description
@ -1565,8 +1400,6 @@ Engine.prototype = {
_hidden: null,
// The engine's name.
_name: null,
// The engine type. See engine types (TYPE_) defined above.
_type: null,
// The name of the charset used to submit the search terms.
_queryCharset: null,
// The engine's raw SearchForm value (URL string pointing to a search form).
@ -1618,10 +1451,8 @@ Engine.prototype = {
_extensionID: null,
/**
* Retrieves the data from the engine's file. If the engine's dataType is
* XML, the document element is placed in the engine's data field. For text
* engines, the data is just read directly from file and placed as an array
* of lines in the engine's data field.
* Retrieves the data from the engine's file.
* The document element is placed in the engine's data field.
*/
_initFromFile: function SRCH_ENG_initFromFile() {
if (!this._file || !this._file.exists())
@ -1632,19 +1463,13 @@ Engine.prototype = {
fileInStream.init(this._file, MODE_RDONLY, FileUtils.PERMS_FILE, false);
if (this._dataType == SEARCH_DATA_XML) {
var domParser = Cc["@mozilla.org/xmlextras/domparser;1"].
createInstance(Ci.nsIDOMParser);
var doc = domParser.parseFromStream(fileInStream, "UTF-8",
this._file.fileSize,
"text/xml");
var domParser = Cc["@mozilla.org/xmlextras/domparser;1"].
createInstance(Ci.nsIDOMParser);
var doc = domParser.parseFromStream(fileInStream, "UTF-8",
this._file.fileSize,
"text/xml");
this._data = doc.documentElement;
} else {
ERROR("Unsuppored engine _dataType in _initFromFile: \"" +
this._dataType + "\"",
Cr.NS_ERROR_UNEXPECTED);
}
this._data = doc.documentElement;
fileInStream.close();
// Now that the data is loaded, initialize the engine object
@ -1652,8 +1477,8 @@ Engine.prototype = {
},
/**
* Retrieves the data from the engine's file asynchronously. If the engine's
* dataType is XML, the document element is placed in the engine's data field.
* Retrieves the data from the engine's file asynchronously.
* The document element is placed in the engine's data field.
*
* @returns {Promise} A promise, resolved successfully if initializing from
* data succeeds, rejected if it fails.
@ -1663,14 +1488,8 @@ Engine.prototype = {
if (!this._file || !(yield OS.File.exists(this._file.path)))
FAIL("File must exist before calling initFromFile!", Cr.NS_ERROR_UNEXPECTED);
if (this._dataType == SEARCH_DATA_XML) {
let fileURI = NetUtil.ioService.newFileURI(this._file);
yield this._retrieveSearchXMLData(fileURI.spec);
} else {
ERROR("Unsuppored engine _dataType in _initFromFile: \"" +
this._dataType + "\"",
Cr.NS_ERROR_UNEXPECTED);
}
let fileURI = NetUtil.ioService.newFileURI(this._file);
yield this._retrieveSearchXMLData(fileURI.spec);
// Now that the data is loaded, initialize the engine object
this._initFromData();
@ -1880,21 +1699,10 @@ Engine.prototype = {
aEngine._file = engineToUpdate._file;
}
switch (aEngine._dataType) {
case SEARCH_DATA_XML:
var parser = Cc["@mozilla.org/xmlextras/domparser;1"].
createInstance(Ci.nsIDOMParser);
var doc = parser.parseFromBuffer(aBytes, aBytes.length, "text/xml");
aEngine._data = doc.documentElement;
break;
case SEARCH_DATA_TEXT:
aEngine._data = aBytes;
break;
default:
promptError();
LOG("_onLoad: Bogus engine _dataType: \"" + this._dataType + "\"");
return;
}
var parser = Cc["@mozilla.org/xmlextras/domparser;1"].
createInstance(Ci.nsIDOMParser);
var doc = parser.parseFromBuffer(aBytes, aBytes.length, "text/xml");
aEngine._data = doc.documentElement;
try {
// Initialize the engine from the obtained data
@ -2133,36 +1941,18 @@ Engine.prototype = {
ENSURE_WARN(this._data, "Can't init an engine with no data!",
Cr.NS_ERROR_UNEXPECTED);
// Find out what type of engine we are
switch (this._dataType) {
case SEARCH_DATA_XML:
if (checkNameSpace(this._data, [MOZSEARCH_LOCALNAME],
[MOZSEARCH_NS_10])) {
// Ensure we have a supported engine type before attempting to parse it.
let element = this._data;
if ((element.localName == MOZSEARCH_LOCALNAME &&
element.namespaceURI == MOZSEARCH_NS_10) ||
(element.localName == OPENSEARCH_LOCALNAME &&
OPENSEARCH_NAMESPACES.indexOf(element.namespaceURI) != -1)) {
LOG("_init: Initing search plugin from " + this._location);
LOG("_init: Initing MozSearch plugin from " + this._location);
this._parse();
this._type = SEARCH_TYPE_MOZSEARCH;
this._parseAsMozSearch();
} else if (checkNameSpace(this._data, [OPENSEARCH_LOCALNAME],
OPENSEARCH_NAMESPACES)) {
LOG("_init: Initing OpenSearch plugin from " + this._location);
this._type = SEARCH_TYPE_OPENSEARCH;
this._parseAsOpenSearch();
} else
FAIL(this._location + " is not a valid search plugin.", Cr.NS_ERROR_FAILURE);
break;
case SEARCH_DATA_TEXT:
LOG("_init: Initing Sherlock plugin from " + this._location);
// the only text-based format we support is Sherlock
this._type = SEARCH_TYPE_SHERLOCK;
this._parseAsSherlock();
}
} else
FAIL(this._location + " is not a valid search plugin.", Cr.NS_ERROR_FAILURE);
// No need to keep a ref to our data (which in some cases can be a document
// element) past this point
@ -2312,16 +2102,11 @@ Engine.prototype = {
this._setIcon(aElement.textContent, isPrefered, width, height);
},
_parseAsMozSearch: function SRCH_ENG_parseAsMoz() {
//forward to the OpenSearch parser
this._parseAsOpenSearch();
},
/**
* Extract search engine information from the collected data to initialize
* the engine object.
*/
_parseAsOpenSearch: function SRCH_ENG_parseAsOS() {
_parse: function SRCH_ENG_parse() {
var doc = this._data;
// The OpenSearch spec sets a default value for the input encoding.
@ -2341,7 +2126,7 @@ Engine.prototype = {
this._parseURL(child);
} catch (ex) {
// Parsing of the element failed, just skip it.
LOG("_parseAsOpenSearch: failed to parse URL child: " + ex);
LOG("_parse: failed to parse URL child: " + ex);
}
break;
case "Image":
@ -2366,324 +2151,13 @@ Engine.prototype = {
break;
case "ExtensionID":
this._extensionID = child.textContent;
breakk;
break;
}
}
if (!this.name || (this._urls.length == 0))
FAIL("_parseAsOpenSearch: No name, or missing URL!", Cr.NS_ERROR_FAILURE);
FAIL("_parse: No name, or missing URL!", Cr.NS_ERROR_FAILURE);
if (!this.supportsResponseType(URLTYPE_SEARCH_HTML))
FAIL("_parseAsOpenSearch: No text/html result type!", Cr.NS_ERROR_FAILURE);
},
/**
* Extract search engine information from the collected data to initialize
* the engine object.
*/
_parseAsSherlock: function SRCH_ENG_parseAsSherlock() {
/**
* Extracts one Sherlock "section" from aSource. A section is essentially
* an HTML element with attributes, but each attribute must be on a new
* line, by definition.
*
* @param aLines
* An array of lines from the sherlock file.
* @param aSection
* The name of the section (e.g. "search" or "browser"). This value
* is not case sensitive.
* @returns an object whose properties correspond to the section's
* attributes.
*/
function getSection(aLines, aSection) {
LOG("_parseAsSherlock::getSection: Sherlock lines:\n" +
aLines.join("\n"));
var lines = aLines;
var startMark = new RegExp("^\\s*<" + aSection.toLowerCase() + "\\s*",
"gi");
var endMark = /\s*>\s*$/gi;
var foundStart = false;
var startLine, numberOfLines;
// Find the beginning and end of the section
for (var i = 0; i < lines.length; i++) {
if (foundStart) {
if (endMark.test(lines[i])) {
numberOfLines = i - startLine;
// Remove the end marker
lines[i] = lines[i].replace(endMark, "");
// If the endmarker was not the only thing on the line, include
// this line in the results
if (lines[i])
numberOfLines++;
break;
}
} else {
if (startMark.test(lines[i])) {
foundStart = true;
// Remove the start marker
lines[i] = lines[i].replace(startMark, "");
startLine = i;
// If the line is empty, don't include it in the result
if (!lines[i])
startLine++;
}
}
}
LOG("_parseAsSherlock::getSection: Start index: " + startLine +
"\nNumber of lines: " + numberOfLines);
lines = lines.splice(startLine, numberOfLines);
LOG("_parseAsSherlock::getSection: Section lines:\n" +
lines.join("\n"));
var section = {};
for (var i = 0; i < lines.length; i++) {
var line = lines[i].trim();
var els = line.split("=");
var name = els.shift().trim().toLowerCase();
var value = els.join("=").trim();
if (!name || !value)
continue;
// Strip leading and trailing whitespace, remove quotes from the
// value, and remove any trailing slashes or ">" characters
value = value.replace(/^["']/, "")
.replace(/["']\s*[\\\/]?>?\s*$/, "") || "";
value = value.trim();
// Don't clobber existing attributes
if (!(name in section))
section[name] = value;
}
return section;
}
/**
* Returns an array of name-value pair arrays representing the Sherlock
* file's input elements. User defined inputs return USER_DEFINED
* as the value. Elements are returned in the order they appear in the
* source file.
*
* Example:
* <input name="foo" value="bar">
* <input name="foopy" user>
* Returns:
* [["foo", "bar"], ["foopy", "{searchTerms}"]]
*
* @param aLines
* An array of lines from the source file.
*/
function getInputs(aLines) {
/**
* Extracts an attribute value from a given a line of text.
* Example: <input value="foo" name="bar">
* Extracts the string |foo| or |bar| given an input aAttr of
* |value| or |name|.
* Attributes may be quoted or unquoted. If unquoted, any whitespace
* indicates the end of the attribute value.
* Example: < value=22 33 name=44\334 >
* Returns |22| for "value" and |44\334| for "name".
*
* @param aAttr
* The name of the attribute for which to obtain the value. This
* value is not case sensitive.
* @param aLine
* The line containing the attribute.
*
* @returns the attribute value, or an empty string if the attribute
* doesn't exist.
*/
function getAttr(aAttr, aLine) {
// Used to determine whether an "input" line from a Sherlock file is a
// "user defined" input.
const userInput = /(\s|["'=])user(\s|[>="'\/\\+]|$)/i;
LOG("_parseAsSherlock::getAttr: Getting attr: \"" +
aAttr + "\" for line: \"" + aLine + "\"");
// We're not case sensitive, but we want to return the attribute value
// in its original case, so create a copy of the source
var lLine = aLine.toLowerCase();
var attr = aAttr.toLowerCase();
var attrStart = lLine.search(new RegExp("\\s" + attr, "i"));
if (attrStart == -1) {
// If this is the "user defined input" (i.e. contains the empty
// "user" attribute), return our special keyword
if (userInput.test(lLine) && attr == "value") {
LOG("_parseAsSherlock::getAttr: Found user input!\nLine:\"" + lLine
+ "\"");
return USER_DEFINED;
}
// The attribute doesn't exist - ignore
LOG("_parseAsSherlock::getAttr: Failed to find attribute:\nLine:\""
+ lLine + "\"\nAttr:\"" + attr + "\"");
return "";
}
var valueStart = lLine.indexOf("=", attrStart) + "=".length;
if (valueStart == -1)
return "";
var quoteStart = lLine.indexOf("\"", valueStart);
if (quoteStart == -1) {
// Unquoted attribute, get the rest of the line, trimmed at the first
// sign of whitespace. If the rest of the line is only whitespace,
// returns a blank string.
return lLine.substr(valueStart).replace(/\s.*$/, "");
} else {
// Make sure that there's only whitespace between the start of the
// value and the first quote. If there is, end the attribute value at
// the first sign of whitespace. This prevents us from falling into
// the next attribute if this is an unquoted attribute followed by a
// quoted attribute.
var betweenEqualAndQuote = lLine.substring(valueStart, quoteStart);
if (/\S/.test(betweenEqualAndQuote))
return lLine.substr(valueStart).replace(/\s.*$/, "");
// Adjust the start index to account for the opening quote
valueStart = quoteStart + "\"".length;
// Find the closing quote
var valueEnd = lLine.indexOf("\"", valueStart);
// If there is no closing quote, just go to the end of the line
if (valueEnd == -1)
valueEnd = aLine.length;
}
return aLine.substring(valueStart, valueEnd);
}
var inputs = [];
LOG("_parseAsSherlock::getInputs: Lines:\n" + aLines);
// Filter out everything but non-inputs
let lines = aLines.filter(function (line) {
return /^\s*<input/i.test(line);
});
LOG("_parseAsSherlock::getInputs: Filtered lines:\n" + lines);
lines.forEach(function (line) {
// Strip leading/trailing whitespace and remove the surrounding markup
// ("<input" and ">")
line = line.trim().replace(/^<input/i, "").replace(/>$/, "");
// If this is one of the "directional" inputs (<inputnext>/<inputprev>)
const directionalInput = /^(prev|next)/i;
if (directionalInput.test(line)) {
// Make it look like a normal input by removing "prev" or "next"
line = line.replace(directionalInput, "");
// If it has a name, give it a dummy value to match previous
// nsInternetSearchService behavior
if (/name\s*=/i.test(line)) {
line += " value=\"0\"";
} else
return; // Line has no name, skip it
}
var attrName = getAttr("name", line);
var attrValue = getAttr("value", line);
LOG("_parseAsSherlock::getInputs: Got input:\nName:\"" + attrName +
"\"\nValue:\"" + attrValue + "\"");
if (attrValue)
inputs.push([attrName, attrValue]);
});
return inputs;
}
function err(aErr) {
FAIL("_parseAsSherlock::err: Sherlock param error:\n" + aErr,
Cr.NS_ERROR_FAILURE);
}
// First try converting our byte array using the default Sherlock encoding.
// If this fails, or if we find a sourceTextEncoding attribute, we need to
// reconvert the byte array using the specified encoding.
var sherlockLines, searchSection, sourceTextEncoding, browserSection;
try {
sherlockLines = sherlockBytesToLines(this._data);
searchSection = getSection(sherlockLines, "search");
browserSection = getSection(sherlockLines, "browser");
sourceTextEncoding = parseInt(searchSection["sourcetextencoding"]);
if (sourceTextEncoding) {
// Re-convert the bytes using the found sourceTextEncoding
sherlockLines = sherlockBytesToLines(this._data, sourceTextEncoding);
searchSection = getSection(sherlockLines, "search");
browserSection = getSection(sherlockLines, "browser");
}
} catch (ex) {
// The conversion using the default charset failed. Remove any non-ascii
// bytes and try to find a sourceTextEncoding.
var asciiBytes = this._data.filter(function (n) {return !(0x80 & n);});
var asciiString = String.fromCharCode.apply(null, asciiBytes);
sherlockLines = asciiString.split(NEW_LINES).filter(isUsefulLine);
searchSection = getSection(sherlockLines, "search");
sourceTextEncoding = parseInt(searchSection["sourcetextencoding"]);
if (sourceTextEncoding) {
sherlockLines = sherlockBytesToLines(this._data, sourceTextEncoding);
searchSection = getSection(sherlockLines, "search");
browserSection = getSection(sherlockLines, "browser");
} else
ERROR("Couldn't find a working charset", Cr.NS_ERROR_FAILURE);
}
LOG("_parseAsSherlock: Search section:\n" + searchSection.toSource());
this._name = searchSection["name"] || err("Missing name!");
this._description = searchSection["description"] || "";
this._queryCharset = searchSection["querycharset"] ||
queryCharsetFromCode(searchSection["queryencoding"]);
this._searchForm = searchSection["searchform"];
this._updateInterval = parseInt(browserSection["updatecheckdays"]);
this._updateURL = browserSection["update"];
this._iconUpdateURL = browserSection["updateicon"];
var method = (searchSection["method"] || "GET").toUpperCase();
var template = searchSection["action"] || err("Missing action!");
var inputs = getInputs(sherlockLines);
LOG("_parseAsSherlock: Inputs:\n" + inputs.toSource());
var url = null;
if (method == "GET") {
// Here's how we construct the input string:
// <input> is first: Name Attr: Prefix Data Example:
// YES EMPTY None <value> TEMPLATE<value>
// YES NON-EMPTY ? <name>=<value> TEMPLATE?<name>=<value>
// NO EMPTY ------------- <ignored> --------------
// NO NON-EMPTY & <name>=<value> TEMPLATE?<n1>=<v1>&<n2>=<v2>
for (var i = 0; i < inputs.length; i++) {
var name = inputs[i][0];
var value = inputs[i][1];
if (i==0) {
if (name == "")
template += USER_DEFINED;
else
template += "?" + name + "=" + value;
} else if (name != "")
template += "&" + name + "=" + value;
}
url = new EngineURL(URLTYPE_SEARCH_HTML, method, template);
} else if (method == "POST") {
// Create the URL object and just add the parameters directly
url = new EngineURL(URLTYPE_SEARCH_HTML, method, template);
for (var i = 0; i < inputs.length; i++) {
var name = inputs[i][0];
var value = inputs[i][1];
if (name)
url.addParam(name, value);
}
} else
err("Invalid method!");
this._urls.push(url);
FAIL("_parse: No text/html result type!", Cr.NS_ERROR_FAILURE);
},
/**
@ -2698,7 +2172,6 @@ Engine.prototype = {
else
this._hasPreferredIcon = false;
this._hidden = aJson._hidden;
this._type = aJson.type || SEARCH_TYPE_MOZSEARCH;
this._queryCharset = aJson.queryCharset || DEFAULT_QUERY_CHARSET;
this.__searchForm = aJson.__searchForm;
this.__installLocation = aJson._installLocation || SEARCH_APP_DIR;
@ -2757,12 +2230,8 @@ Engine.prototype = {
json._iconUpdateURL = this._iconUpdateURL;
if (!this._hasPreferredIcon || !aFilter)
json._hasPreferredIcon = this._hasPreferredIcon;
if (this.type != SEARCH_TYPE_MOZSEARCH || !aFilter)
json.type = this.type;
if (this.queryCharset != DEFAULT_QUERY_CHARSET || !aFilter)
json.queryCharset = this.queryCharset;
if (this._dataType != SEARCH_DATA_XML || !aFilter)
json._dataType = this._dataType;
if (!this._readOnly || !aFilter)
json._readOnly = this._readOnly;
if (this._extensionID) {
@ -3144,10 +2613,6 @@ Engine.prototype = {
return this._name;
},
get type() {
return this._type;
},
get searchForm() {
return this._getSearchFormWithPurpose();
},
@ -3178,7 +2643,7 @@ Engine.prototype = {
get queryCharset() {
if (this._queryCharset)
return this._queryCharset;
return this._queryCharset = queryCharsetFromCode(/* get the default */);
return this._queryCharset = "windows-1252"; // the default
},
// from nsISearchEngine
@ -4041,15 +3506,6 @@ SearchService.prototype = {
// Schedule the engine's next update, if it isn't already.
if (!engineMetadataService.getAttr(aEngine, "updateexpir"))
engineUpdateService.scheduleNextUpdate(aEngine);
// We need to save the engine's _dataType, if this is the first time the
// engine is added to the dataStore, since ._dataType isn't persisted
// and will change on the next startup (since the engine will then be
// XML). We need this so that we know how to load any future updates from
// this engine.
if (!engineMetadataService.getAttr(aEngine, "updatedatatype"))
engineMetadataService.setAttr(aEngine, "updatedatatype",
aEngine._dataType);
}
},
@ -4062,10 +3518,10 @@ SearchService.prototype = {
try {
let engine;
if (json.filePath)
engine = new Engine({type: "filePath", value: json.filePath}, json._dataType,
engine = new Engine({type: "filePath", value: json.filePath},
json._readOnly);
else if (json._url)
engine = new Engine({type: "uri", value: json._url}, json._dataType, json._readOnly);
engine = new Engine({type: "uri", value: json._url}, json._readOnly);
engine._initWithJSON(json);
this._addEngineToStore(engine);
@ -4103,7 +3559,7 @@ SearchService.prototype = {
var addedEngine = null;
try {
addedEngine = new Engine(file, SEARCH_DATA_XML, !isWritable);
addedEngine = new Engine(file, !isWritable);
addedEngine._initFromFile();
} catch (ex) {
LOG("_loadEnginesFromDir: Failed to load " + file.path + "!\n" + ex);
@ -4151,7 +3607,7 @@ SearchService.prototype = {
try {
let file = new FileUtils.File(osfile.path);
let isWritable = isInProfile;
addedEngine = new Engine(file, SEARCH_DATA_XML, !isWritable);
addedEngine = new Engine(file, !isWritable);
yield checkForSyncCompletion(addedEngine._asyncInitFromFile());
} catch (ex if ex.result != Cr.NS_ERROR_ALREADY_INITIALIZED) {
LOG("_asyncLoadEnginesFromDir: Failed to load " + osfile.path + "!\n" + ex);
@ -4168,7 +3624,7 @@ SearchService.prototype = {
try {
LOG("_loadFromChromeURLs: loading engine from chrome url: " + url);
let engine = new Engine(makeURI(url), SEARCH_DATA_XML, true);
let engine = new Engine(makeURI(url), true);
engine._initFromURISync();
@ -4193,7 +3649,7 @@ SearchService.prototype = {
for (let url of aURLs) {
try {
LOG("_asyncLoadFromChromeURLs: loading engine from chrome url: " + url);
let engine = new Engine(NetUtil.newURI(url), SEARCH_DATA_XML, true);
let engine = new Engine(NetUtil.newURI(url), true);
yield checkForSyncCompletion(engine._asyncInitFromURI());
engines.push(engine);
} catch (ex if ex.result != Cr.NS_ERROR_ALREADY_INITIALIZED) {
@ -4640,7 +4096,7 @@ SearchService.prototype = {
if (this._engines[aName])
FAIL("An engine with that name already exists!", Cr.NS_ERROR_FILE_ALREADY_EXISTS);
var engine = new Engine(getSanitizedFile(aName), SEARCH_DATA_XML, false);
var engine = new Engine(getSanitizedFile(aName), false);
engine._initFromMetadata(aName, aIconURL, aAlias, aDescription,
aMethod, aTemplate, aExtensionID);
this._addEngineToStore(engine);
@ -4652,7 +4108,7 @@ SearchService.prototype = {
this._ensureInitialized();
try {
var uri = makeURI(aEngineURL);
var engine = new Engine(uri, aDataType, false);
var engine = new Engine(uri, false);
if (aCallback) {
engine._installCallback = function (errorCode) {
try {
@ -5542,14 +4998,8 @@ var engineUpdateService = {
return;
}
let dataType = engineMetadataService.getAttr(engine, "updatedatatype");
if (!dataType) {
ULOG("No loadtype to update engine!");
return;
}
ULOG("updating " + engine.name + " from " + updateURI.spec);
testEngine = new Engine(updateURI, dataType, false);
testEngine = new Engine(updateURI, false);
testEngine._engineToUpdate = engine;
testEngine._initFromURIAndLoad();
} else

View File

@ -22,29 +22,23 @@ nsSidebar.prototype = {
.getInterface(Ci.nsIContentFrameMessageManager);
},
// The suggestedTitle and suggestedCategory parameters are ignored, but remain
// for backward compatibility.
// Deprecated, only left here to avoid breaking old browser-detection scripts.
addSearchEngine: function(engineURL, iconURL, suggestedTitle, suggestedCategory) {
let dataType = SHERLOCK_FILE_EXT_REGEXP.test(engineURL) ?
Ci.nsISearchEngine.DATA_TEXT :
Ci.nsISearchEngine.DATA_XML;
if (SHERLOCK_FILE_EXT_REGEXP.test(engineURL)) {
Cu.reportError("Installing Sherlock search plugins is no longer supported.");
return;
}
this.mm.sendAsyncMessage("Search:AddEngine", {
pageURL: this.window.document.documentURIObject.spec,
engineURL,
type: dataType,
iconURL
});
this.AddSearchProvider(engineURL);
},
// This function exists largely to implement window.external.AddSearchProvider(),
// to match other browsers' APIs. The capitalization, although nonstandard here,
// is therefore important.
// This function implements window.external.AddSearchProvider().
// The capitalization, although nonstandard here, is to match other browsers'
// APIs and is therefore important.
AddSearchProvider: function(engineURL) {
this.mm.sendAsyncMessage("Search:AddEngine", {
pageURL: this.window.document.documentURIObject.spec,
engineURL,
type: Ci.nsISearchEngine.DATA_XML
engineURL
});
},

View File

@ -1,18 +0,0 @@
<SEARCH
version="1"
name="Sherlock test search engine"
description="A test search engine for testing sherlock"
method="GET"
action="http://getfirefox.com"
searchform="http://getfirefox.com"
>
<input name="q" user>
</search>
<BROWSER
update="http://getfirefox.com"
updateIcon="http://getfirefox.com"
updatecheckdays="7"
>

View File

@ -17,21 +17,12 @@ function handleRequest(request, response) {
return;
}
engineData.engineType = engineData.engineType || Ci.nsISearchEngine.TYPE_OPENSEARCH;
engineData.name = engineData.name || "Generated test engine";
engineData.description = engineData.description || "Generated test engine description";
engineData.method = engineData.method || "GET";
response.setStatusLine(request.httpVersion, 200, "OK");
switch (engineData.engineType) {
case Ci.nsISearchEngine.TYPE_OPENSEARCH:
createOpenSearchEngine(response, engineData);
break;
default:
response.setStatusLine(request.httpVersion, 404, "Unsupported engine type");
break;
}
createOpenSearchEngine(response, engineData);
}
/**

View File

@ -391,8 +391,6 @@ function useHttpServer() {
* {
* name: Engine name, used to wait for it to be loaded.
* xmlFileName: Name of the XML file in the "data" folder.
* srcFileName: Name of the SRC file in the "data" folder.
* iconFileName: Name of the icon associated to the SRC file.
* details: Array containing the parameters of addEngineWithDetails,
* except for the engine name. Alternative to xmlFileName.
* }
@ -425,11 +423,7 @@ var addTestEngines = Task.async(function* (aItems) {
if (item.xmlFileName) {
Services.search.addEngine(gDataUrl + item.xmlFileName,
Ci.nsISearchEngine.DATA_XML, null, false);
} else if (item.srcFileName) {
Services.search.addEngine(gDataUrl + item.srcFileName,
Ci.nsISearchEngine.DATA_TEXT,
gDataUrl + item.iconFileName, false);
null, null, false);
} else {
Services.search.addEngineWithDetails(item.name, ...item.details);
}

View File

@ -47,8 +47,7 @@ add_test(function simple_callback_test() {
do_throw("search callback returned error: " + errorCode);
}
}
Services.search.addEngine(gDataUrl + "engine.xml",
Ci.nsISearchEngine.DATA_XML,
Services.search.addEngine(gDataUrl + "engine.xml", null,
null, false, searchCallback);
});
@ -65,8 +64,7 @@ add_test(function duplicate_failure_test() {
}
}
// Re-add the same engine added in the previous test
Services.search.addEngine(gDataUrl + "engine.xml",
Ci.nsISearchEngine.DATA_XML,
Services.search.addEngine(gDataUrl + "engine.xml", null,
null, false, searchCallback);
});
@ -83,8 +81,7 @@ add_test(function load_failure_test() {
}
}
// Try adding an engine that doesn't exist
Services.search.addEngine("http://invalid/data/engine.xml",
Ci.nsISearchEngine.DATA_XML,
Services.search.addEngine("http://invalid/data/engine.xml", null,
null, false, searchCallback);
});

View File

@ -236,7 +236,6 @@ var EXPECTED_ENGINE = {
alias: null,
description: "A test search engine (based on Google search)",
searchForm: "http://www.google.com/",
type: Ci.nsISearchEngine.TYPE_MOZSEARCH,
wrappedJSObject: {
_extensionID: "test-addon-id@mozilla.org",
"_iconURL": "data:image/png;base64,AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs9Pt8xetPtu9FsfFNtu%2BTzvb2%2B%2Fne4dFJeBw0egA%2FfAJAfAA8ewBBegAAAAD%2B%2FPtft98Mp%2BwWsfAVsvEbs%2FQeqvF8xO7%2F%2F%2F63yqkxdgM7gwE%2FggM%2BfQA%2BegBDeQDe7PIbotgQufcMufEPtfIPsvAbs%2FQvq%2Bfz%2Bf%2F%2B%2B%2FZKhR05hgBBhQI8hgBAgAI9ewD0%2B%2Fg3pswAtO8Cxf4Kw%2FsJvvYAqupKsNv%2B%2Fv7%2F%2FP5VkSU0iQA7jQA9hgBDgQU%2BfQH%2F%2Ff%2FQ6fM4sM4KsN8AteMCruIqqdbZ7PH8%2Fv%2Fg6Nc%2Fhg05kAA8jAM9iQI%2BhQA%2BgQDQu6b97uv%2F%2F%2F7V8Pqw3eiWz97q8%2Ff%2F%2F%2F%2F7%2FPptpkkqjQE4kwA7kAA5iwI8iAA8hQCOSSKdXjiyflbAkG7u2s%2F%2B%2F%2F39%2F%2F7r8utrqEYtjQE8lgA7kwA7kwA9jwA9igA9hACiWSekVRyeSgiYSBHx6N%2F%2B%2Fv7k7OFRmiYtlAA5lwI7lwI4lAA7kgI9jwE9iwI4iQCoVhWcTxCmb0K%2BooT8%2Fv%2F7%2F%2F%2FJ2r8fdwI1mwA3mQA3mgA8lAE8lAE4jwA9iwE%2BhwGfXifWvqz%2B%2Ff%2F58u%2Fev6Dt4tr%2B%2F%2F2ZuIUsggA7mgM6mAM3lgA5lgA6kQE%2FkwBChwHt4dv%2F%2F%2F728ei1bCi7VAC5XQ7kz7n%2F%2F%2F6bsZkgcB03lQA9lgM7kwA2iQktZToPK4r9%2F%2F%2F9%2F%2F%2FSqYK5UwDKZAS9WALIkFn%2B%2F%2F3%2F%2BP8oKccGGcIRJrERILYFEMwAAuEAAdX%2F%2Ff7%2F%2FP%2B%2BfDvGXQLIZgLEWgLOjlf7%2F%2F%2F%2F%2F%2F9QU90EAPQAAf8DAP0AAfMAAOUDAtr%2F%2F%2F%2F7%2B%2Fu2bCTIYwDPZgDBWQDSr4P%2F%2Fv%2F%2F%2FP5GRuABAPkAA%2FwBAfkDAPAAAesAAN%2F%2F%2B%2Fz%2F%2F%2F64g1C5VwDMYwK8Yg7y5tz8%2Fv%2FV1PYKDOcAAP0DAf4AAf0AAfYEAOwAAuAAAAD%2F%2FPvi28ymXyChTATRrIb8%2F%2F3v8fk6P8MAAdUCAvoAAP0CAP0AAfYAAO4AAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAA",

View File

@ -31,8 +31,7 @@ function run_test() {
add_task(function* test_nodb_pluschanges() {
let [engine1, engine2] = yield addTestEngines([
{ name: "Test search engine", xmlFileName: "engine.xml" },
{ name: "Sherlock test search engine", srcFileName: "engine.src",
iconFileName: "ico-size-16x16-png.ico" },
{ name: "A second test engine", xmlFileName: "engine2.xml"},
]);
let search = Services.search;
@ -54,7 +53,7 @@ add_task(function* test_nodb_pluschanges() {
// Check that the entries are placed as specified correctly
let json = getSearchMetadata();
do_check_eq(json["[app]/test-search-engine.xml"].order, 1);
do_check_eq(json["[profile]/sherlock-test-search-engine.xml"].order, 2);
do_check_eq(json["[profile]/a-second-test-engine.xml"].order, 2);
do_print("Cleaning up");
removeMetadata();

View File

@ -68,7 +68,5 @@ function run_test() {
Services.obs.addObserver(search_observer, "browser-search-engine-modified", false);
Services.search.addEngine(gDataUrl + "engine.xml",
Ci.nsISearchEngine.DATA_XML,
null, false);
Services.search.addEngine(gDataUrl + "engine.xml", null, null, false);
}

View File

@ -30,8 +30,6 @@ add_task(function* test_parseSubmissionURL() {
"GET", "http://www.xn--bcher-kva.ch/search"] },
// The following engines cannot identify the search parameter.
{ name: "A second test engine", xmlFileName: "engine2.xml" },
{ name: "Sherlock test search engine", srcFileName: "engine.src",
iconFileName: "ico-size-16x16-png.ico" },
{ name: "bacon", details: ["", "bacon", "Search Bacon", "GET",
"http://www.bacon.moz/search?q={searchTerms}"] },
]);
@ -107,12 +105,6 @@ add_task(function* test_parseSubmissionURL() {
do_check_eq(Services.search.parseSubmissionURL(
"https://duckduckgo.com/?q=test").engine, null);
// Sherlock engines are not supported.
do_check_eq(Services.search.parseSubmissionURL(
"http://getfirefox.com?q=test").engine, null);
do_check_eq(Services.search.parseSubmissionURL(
"http://getfirefox.com/?q=test").engine, null);
// HTTP and HTTPS schemes are interchangeable.
url = "https://www.google.com/search?q=caff%C3%A8";
result = Services.search.parseSubmissionURL(url);

View File

@ -28,8 +28,7 @@ function run_test() {
add_task(function* test_save_sorted_engines() {
let [engine1, engine2] = yield addTestEngines([
{ name: "Test search engine", xmlFileName: "engine.xml" },
{ name: "Sherlock test search engine", srcFileName: "engine.src",
iconFileName: "ico-size-16x16-png.ico" },
{ name: "A second test engine", xmlFileName: "engine2.xml"},
]);
let search = Services.search;
@ -45,7 +44,7 @@ add_task(function* test_save_sorted_engines() {
// Check that the entries are placed as specified correctly
let json = getSearchMetadata();
do_check_eq(json["[app]/test-search-engine.xml"].order, 1);
do_check_eq(json["[profile]/sherlock-test-search-engine.xml"].order, 2);
do_check_eq(json["[profile]/a-second-test-engine.xml"].order, 2);
// Test removing an engine
search.removeEngine(engine1);
@ -54,7 +53,7 @@ add_task(function* test_save_sorted_engines() {
// Check that the order of the remaining engine was updated correctly
json = getSearchMetadata();
do_check_eq(json["[profile]/sherlock-test-search-engine.xml"].order, 1);
do_check_eq(json["[profile]/a-second-test-engine.xml"].order, 1);
// Test adding a new engine
search.addEngineWithDetails("foo", "", "foo", "", "GET",

View File

@ -36,21 +36,18 @@ function run_test() {
add_task(function* add_test_engines() {
let getEngineData = {
baseURL: gDataUrl,
engineType: Ci.nsISearchEngine.TYPE_OPENSEARCH,
name: "GET suggestion engine",
method: "GET",
};
let postEngineData = {
baseURL: gDataUrl,
engineType: Ci.nsISearchEngine.TYPE_OPENSEARCH,
name: "POST suggestion engine",
method: "POST",
};
let unresolvableEngineData = {
baseURL: "http://example.invalid/",
engineType: Ci.nsISearchEngine.TYPE_OPENSEARCH,
name: "Offline suggestion engine",
method: "GET",
};

View File

@ -20,8 +20,7 @@ function run_test() {
add_task(function test_batchTask() {
let [engine1, engine2] = yield addTestEngines([
{ name: "Test search engine", xmlFileName: "engine.xml" },
{ name: "Sherlock test search engine", srcFileName: "engine.src",
iconFileName: "ico-size-16x16-png.ico" },
{ name: "A second test engine", xmlFileName: "engine2.xml"},
]);
// Test that files are written correctly.

View File

@ -5,7 +5,6 @@ firefox-appdir = browser
skip-if = toolkit == 'android' || toolkit == 'gonk'
support-files =
data/chrome.manifest
data/engine.src
data/engine.xml
data/engine2.xml
data/engine-addon.xml