diff -r 000000000000 -r 6474c204b198 browser/modules/ContentSearch.jsm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/browser/modules/ContentSearch.jsm Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,149 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +"use strict"; + +this.EXPORTED_SYMBOLS = [ + "ContentSearch", +]; + +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; + +Cu.import("resource://gre/modules/Services.jsm"); + +const INBOUND_MESSAGE = "ContentSearch"; +const OUTBOUND_MESSAGE = INBOUND_MESSAGE; + +/** + * ContentSearch receives messages named INBOUND_MESSAGE and sends messages + * named OUTBOUND_MESSAGE. The data of each message is expected to look like + * { type, data }. type is the message's type (or subtype if you consider the + * type of the message itself to be INBOUND_MESSAGE), and data is data that is + * specific to the type. + * + * Inbound messages have the following types: + * + * GetState + * Retrieves the current search engine state. + * data: null + * ManageEngines + * Opens the search engine management window. + * data: null + * Search + * Performs a search. + * data: an object { engineName, searchString, whence } + * SetCurrentEngine + * Sets the current engine. + * data: the name of the engine + * + * Outbound messages have the following types: + * + * CurrentEngine + * Sent when the current engine changes. + * data: see _currentEngineObj + * State + * Sent in reply to GetState and when the state changes. + * data: see _currentStateObj + */ + +this.ContentSearch = { + + init: function () { + Cc["@mozilla.org/globalmessagemanager;1"]. + getService(Ci.nsIMessageListenerManager). + addMessageListener(INBOUND_MESSAGE, this); + Services.obs.addObserver(this, "browser-search-engine-modified", false); + }, + + receiveMessage: function (msg) { + let methodName = "on" + msg.data.type; + if (methodName in this) { + this[methodName](msg, msg.data.data); + } + }, + + onGetState: function (msg, data) { + this._reply(msg, "State", this._currentStateObj()); + }, + + onSearch: function (msg, data) { + let expectedDataProps = [ + "engineName", + "searchString", + "whence", + ]; + for (let prop of expectedDataProps) { + if (!(prop in data)) { + Cu.reportError("Message data missing required property: " + prop); + return; + } + } + let browserWin = msg.target.ownerDocument.defaultView; + let engine = Services.search.getEngineByName(data.engineName); + browserWin.BrowserSearch.recordSearchInHealthReport(engine, data.whence); + let submission = engine.getSubmission(data.searchString, "", data.whence); + browserWin.loadURI(submission.uri.spec, null, submission.postData); + }, + + onSetCurrentEngine: function (msg, data) { + Services.search.currentEngine = Services.search.getEngineByName(data); + }, + + onManageEngines: function (msg, data) { + let browserWin = msg.target.ownerDocument.defaultView; + browserWin.BrowserSearch.searchBar.openManager(null); + }, + + observe: function (subj, topic, data) { + switch (topic) { + case "browser-search-engine-modified": + if (data == "engine-current") { + this._broadcast("CurrentEngine", this._currentEngineObj()); + } + else if (data != "engine-default") { + // engine-default is always sent with engine-current and isn't otherwise + // relevant to content searches. + this._broadcast("State", this._currentStateObj()); + } + break; + } + }, + + _reply: function (msg, type, data) { + msg.target.messageManager.sendAsyncMessage(...this._msgArgs(type, data)); + }, + + _broadcast: function (type, data) { + Cc["@mozilla.org/globalmessagemanager;1"]. + getService(Ci.nsIMessageListenerManager). + broadcastAsyncMessage(...this._msgArgs(type, data)); + }, + + _msgArgs: function (type, data) { + return [OUTBOUND_MESSAGE, { + type: type, + data: data, + }]; + }, + + _currentStateObj: function () { + return { + engines: Services.search.getVisibleEngines().map(engine => { + return { + name: engine.name, + iconURI: engine.getIconURLBySize(16, 16), + }; + }), + currentEngine: this._currentEngineObj(), + }; + }, + + _currentEngineObj: function () { + return { + name: Services.search.currentEngine.name, + logoURI: Services.search.currentEngine.getIconURLBySize(65, 26), + logo2xURI: Services.search.currentEngine.getIconURLBySize(130, 52), + }; + }, +};