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: const TEST_MSG = "ContentSearchTest"; michael@0: const CONTENT_SEARCH_MSG = "ContentSearch"; michael@0: const TEST_CONTENT_SCRIPT_BASENAME = "contentSearch.js"; michael@0: michael@0: function generatorTest() { michael@0: // nextStep() drives the iterator returned by this function. This function's michael@0: // iterator in turn drives the iterator of each test below. michael@0: let currentTestIter = yield startNextTest(); michael@0: let arg = undefined; michael@0: while (currentTestIter) { michael@0: try { michael@0: currentTestIter.send(arg); michael@0: arg = yield null; michael@0: } michael@0: catch (err if err instanceof StopIteration) { michael@0: currentTestIter = yield startNextTest(); michael@0: arg = undefined; michael@0: } michael@0: } michael@0: } michael@0: michael@0: function startNextTest() { michael@0: if (!gTests.length) { michael@0: setTimeout(() => nextStep(null), 0); michael@0: return; michael@0: } michael@0: let nextTestGen = gTests.shift(); michael@0: let nextTestIter = nextTestGen(); michael@0: addTab(() => { michael@0: info("Starting test " + nextTestGen.name); michael@0: nextStep(nextTestIter); michael@0: }); michael@0: } michael@0: michael@0: function addTest(testGen) { michael@0: gTests.push(testGen); michael@0: } michael@0: michael@0: var gTests = []; michael@0: var gMsgMan; michael@0: michael@0: addTest(function GetState() { michael@0: gMsgMan.sendAsyncMessage(TEST_MSG, { michael@0: type: "GetState", michael@0: }); michael@0: let msg = yield waitForTestMsg("State"); michael@0: checkMsg(msg, { michael@0: type: "State", michael@0: data: currentStateObj(), michael@0: }); michael@0: }); michael@0: michael@0: addTest(function SetCurrentEngine() { michael@0: let newCurrentEngine = null; michael@0: let oldCurrentEngine = Services.search.currentEngine; michael@0: let engines = Services.search.getVisibleEngines(); michael@0: for (let engine of engines) { michael@0: if (engine != oldCurrentEngine) { michael@0: newCurrentEngine = engine; michael@0: break; michael@0: } michael@0: } michael@0: if (!newCurrentEngine) { michael@0: info("Couldn't find a non-selected search engine, " + michael@0: "skipping this part of the test"); michael@0: return; michael@0: } michael@0: gMsgMan.sendAsyncMessage(TEST_MSG, { michael@0: type: "SetCurrentEngine", michael@0: data: newCurrentEngine.name, michael@0: }); michael@0: Services.obs.addObserver(function obs(subj, topic, data) { michael@0: info("Test observed " + data); michael@0: if (data == "engine-current") { michael@0: ok(true, "Test observed engine-current"); michael@0: Services.obs.removeObserver(obs, "browser-search-engine-modified", false); michael@0: nextStep(); michael@0: } michael@0: }, "browser-search-engine-modified", false); michael@0: info("Waiting for test to observe engine-current..."); michael@0: waitForTestMsg("CurrentEngine"); michael@0: let maybeMsg1 = yield null; michael@0: let maybeMsg2 = yield null; michael@0: let msg = maybeMsg1 || maybeMsg2; michael@0: ok(!!msg, michael@0: "Sanity check: One of the yields is for waitForTestMsg and should have " + michael@0: "therefore produced a message object"); michael@0: checkMsg(msg, { michael@0: type: "CurrentEngine", michael@0: data: currentEngineObj(newCurrentEngine), michael@0: }); michael@0: michael@0: Services.search.currentEngine = oldCurrentEngine; michael@0: let msg = yield waitForTestMsg("CurrentEngine"); michael@0: checkMsg(msg, { michael@0: type: "CurrentEngine", michael@0: data: currentEngineObj(oldCurrentEngine), michael@0: }); michael@0: }); michael@0: michael@0: addTest(function ManageEngines() { michael@0: gMsgMan.sendAsyncMessage(TEST_MSG, { michael@0: type: "ManageEngines", michael@0: }); michael@0: let winWatcher = Cc["@mozilla.org/embedcomp/window-watcher;1"]. michael@0: getService(Ci.nsIWindowWatcher); michael@0: winWatcher.registerNotification(function onOpen(subj, topic, data) { michael@0: if (topic == "domwindowopened" && subj instanceof Ci.nsIDOMWindow) { michael@0: subj.addEventListener("load", function onLoad() { michael@0: subj.removeEventListener("load", onLoad); michael@0: if (subj.document.documentURI == michael@0: "chrome://browser/content/search/engineManager.xul") { michael@0: winWatcher.unregisterNotification(onOpen); michael@0: ok(true, "Observed search manager window open"); michael@0: is(subj.opener, window, michael@0: "Search engine manager opener should be this chrome window"); michael@0: subj.close(); michael@0: nextStep(); michael@0: } michael@0: }); michael@0: } michael@0: }); michael@0: info("Waiting for search engine manager window to open..."); michael@0: yield null; michael@0: }); michael@0: michael@0: addTest(function modifyEngine() { michael@0: let engine = Services.search.currentEngine; michael@0: let oldAlias = engine.alias; michael@0: engine.alias = "ContentSearchTest"; michael@0: let msg = yield waitForTestMsg("State"); michael@0: checkMsg(msg, { michael@0: type: "State", michael@0: data: currentStateObj(), michael@0: }); michael@0: engine.alias = oldAlias; michael@0: msg = yield waitForTestMsg("State"); michael@0: checkMsg(msg, { michael@0: type: "State", michael@0: data: currentStateObj(), michael@0: }); michael@0: }); michael@0: michael@0: addTest(function search() { michael@0: let engine = Services.search.currentEngine; michael@0: let data = { michael@0: engineName: engine.name, michael@0: searchString: "ContentSearchTest", michael@0: whence: "ContentSearchTest", michael@0: }; michael@0: gMsgMan.sendAsyncMessage(TEST_MSG, { michael@0: type: "Search", michael@0: data: data, michael@0: }); michael@0: let submissionURL = michael@0: engine.getSubmission(data.searchString, "", data.whence).uri.spec; michael@0: let listener = { michael@0: onStateChange: function (webProg, req, flags, status) { michael@0: let url = req.originalURI.spec; michael@0: info("onStateChange " + url); michael@0: let docStart = Ci.nsIWebProgressListener.STATE_IS_DOCUMENT | michael@0: Ci.nsIWebProgressListener.STATE_START; michael@0: if ((flags & docStart) && webProg.isTopLevel && url == submissionURL) { michael@0: gBrowser.removeProgressListener(listener); michael@0: ok(true, "Search URL loaded"); michael@0: req.cancel(Components.results.NS_ERROR_FAILURE); michael@0: nextStep(); michael@0: } michael@0: } michael@0: }; michael@0: gBrowser.addProgressListener(listener); michael@0: info("Waiting for search URL to load: " + submissionURL); michael@0: yield null; michael@0: }); michael@0: michael@0: function checkMsg(actualMsg, expectedMsgData) { michael@0: SimpleTest.isDeeply(actualMsg.data, expectedMsgData, "Checking message"); michael@0: } michael@0: michael@0: function waitForMsg(name, type, callback) { michael@0: info("Waiting for " + name + " message " + type + "..."); michael@0: gMsgMan.addMessageListener(name, function onMsg(msg) { michael@0: info("Received " + name + " message " + msg.data.type + "\n"); michael@0: if (msg.data.type == type) { michael@0: gMsgMan.removeMessageListener(name, onMsg); michael@0: (callback || nextStep)(msg); michael@0: } michael@0: }); michael@0: } michael@0: michael@0: function waitForTestMsg(type, callback) { michael@0: waitForMsg(TEST_MSG, type, callback); michael@0: } michael@0: michael@0: function addTab(onLoad) { michael@0: let tab = gBrowser.addTab(); michael@0: gBrowser.selectedTab = tab; michael@0: tab.linkedBrowser.addEventListener("load", function load() { michael@0: tab.removeEventListener("load", load, true); michael@0: let url = getRootDirectory(gTestPath) + TEST_CONTENT_SCRIPT_BASENAME; michael@0: gMsgMan = tab.linkedBrowser.messageManager; michael@0: gMsgMan.sendAsyncMessage(CONTENT_SEARCH_MSG, { michael@0: type: "AddToWhitelist", michael@0: data: ["about:blank"], michael@0: }); michael@0: waitForMsg(CONTENT_SEARCH_MSG, "AddToWhitelistAck", () => { michael@0: gMsgMan.loadFrameScript(url, false); michael@0: onLoad(); michael@0: }); michael@0: }, true); michael@0: registerCleanupFunction(() => gBrowser.removeTab(tab)); michael@0: } michael@0: michael@0: function currentStateObj() { michael@0: return { michael@0: engines: Services.search.getVisibleEngines().map(engine => { michael@0: return { michael@0: name: engine.name, michael@0: iconURI: engine.getIconURLBySize(16, 16), michael@0: }; michael@0: }), michael@0: currentEngine: currentEngineObj(), michael@0: }; michael@0: } michael@0: michael@0: function currentEngineObj(expectedCurrentEngine) { michael@0: if (expectedCurrentEngine) { michael@0: is(Services.search.currentEngine.name, expectedCurrentEngine.name, michael@0: "Sanity check: expected current engine"); michael@0: } michael@0: return { michael@0: name: Services.search.currentEngine.name, michael@0: logoURI: Services.search.currentEngine.getIconURLBySize(65, 26), michael@0: logo2xURI: Services.search.currentEngine.getIconURLBySize(130, 52), michael@0: }; michael@0: }