Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 "use strict";
7 this.EXPORTED_SYMBOLS = [
8 "ContentSearch",
9 ];
11 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
13 Cu.import("resource://gre/modules/Services.jsm");
15 const INBOUND_MESSAGE = "ContentSearch";
16 const OUTBOUND_MESSAGE = INBOUND_MESSAGE;
18 /**
19 * ContentSearch receives messages named INBOUND_MESSAGE and sends messages
20 * named OUTBOUND_MESSAGE. The data of each message is expected to look like
21 * { type, data }. type is the message's type (or subtype if you consider the
22 * type of the message itself to be INBOUND_MESSAGE), and data is data that is
23 * specific to the type.
24 *
25 * Inbound messages have the following types:
26 *
27 * GetState
28 * Retrieves the current search engine state.
29 * data: null
30 * ManageEngines
31 * Opens the search engine management window.
32 * data: null
33 * Search
34 * Performs a search.
35 * data: an object { engineName, searchString, whence }
36 * SetCurrentEngine
37 * Sets the current engine.
38 * data: the name of the engine
39 *
40 * Outbound messages have the following types:
41 *
42 * CurrentEngine
43 * Sent when the current engine changes.
44 * data: see _currentEngineObj
45 * State
46 * Sent in reply to GetState and when the state changes.
47 * data: see _currentStateObj
48 */
50 this.ContentSearch = {
52 init: function () {
53 Cc["@mozilla.org/globalmessagemanager;1"].
54 getService(Ci.nsIMessageListenerManager).
55 addMessageListener(INBOUND_MESSAGE, this);
56 Services.obs.addObserver(this, "browser-search-engine-modified", false);
57 },
59 receiveMessage: function (msg) {
60 let methodName = "on" + msg.data.type;
61 if (methodName in this) {
62 this[methodName](msg, msg.data.data);
63 }
64 },
66 onGetState: function (msg, data) {
67 this._reply(msg, "State", this._currentStateObj());
68 },
70 onSearch: function (msg, data) {
71 let expectedDataProps = [
72 "engineName",
73 "searchString",
74 "whence",
75 ];
76 for (let prop of expectedDataProps) {
77 if (!(prop in data)) {
78 Cu.reportError("Message data missing required property: " + prop);
79 return;
80 }
81 }
82 let browserWin = msg.target.ownerDocument.defaultView;
83 let engine = Services.search.getEngineByName(data.engineName);
84 browserWin.BrowserSearch.recordSearchInHealthReport(engine, data.whence);
85 let submission = engine.getSubmission(data.searchString, "", data.whence);
86 browserWin.loadURI(submission.uri.spec, null, submission.postData);
87 },
89 onSetCurrentEngine: function (msg, data) {
90 Services.search.currentEngine = Services.search.getEngineByName(data);
91 },
93 onManageEngines: function (msg, data) {
94 let browserWin = msg.target.ownerDocument.defaultView;
95 browserWin.BrowserSearch.searchBar.openManager(null);
96 },
98 observe: function (subj, topic, data) {
99 switch (topic) {
100 case "browser-search-engine-modified":
101 if (data == "engine-current") {
102 this._broadcast("CurrentEngine", this._currentEngineObj());
103 }
104 else if (data != "engine-default") {
105 // engine-default is always sent with engine-current and isn't otherwise
106 // relevant to content searches.
107 this._broadcast("State", this._currentStateObj());
108 }
109 break;
110 }
111 },
113 _reply: function (msg, type, data) {
114 msg.target.messageManager.sendAsyncMessage(...this._msgArgs(type, data));
115 },
117 _broadcast: function (type, data) {
118 Cc["@mozilla.org/globalmessagemanager;1"].
119 getService(Ci.nsIMessageListenerManager).
120 broadcastAsyncMessage(...this._msgArgs(type, data));
121 },
123 _msgArgs: function (type, data) {
124 return [OUTBOUND_MESSAGE, {
125 type: type,
126 data: data,
127 }];
128 },
130 _currentStateObj: function () {
131 return {
132 engines: Services.search.getVisibleEngines().map(engine => {
133 return {
134 name: engine.name,
135 iconURI: engine.getIconURLBySize(16, 16),
136 };
137 }),
138 currentEngine: this._currentEngineObj(),
139 };
140 },
142 _currentEngineObj: function () {
143 return {
144 name: Services.search.currentEngine.name,
145 logoURI: Services.search.currentEngine.getIconURLBySize(65, 26),
146 logo2xURI: Services.search.currentEngine.getIconURLBySize(130, 52),
147 };
148 },
149 };