diff options
Diffstat (limited to 'browser/components/newtab/NewTabMessages.jsm')
-rw-r--r-- | browser/components/newtab/NewTabMessages.jsm | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/browser/components/newtab/NewTabMessages.jsm b/browser/components/newtab/NewTabMessages.jsm new file mode 100644 index 000000000..0816ed65a --- /dev/null +++ b/browser/components/newtab/NewTabMessages.jsm @@ -0,0 +1,242 @@ +/* global + NewTabWebChannel, + NewTabPrefsProvider, + PlacesProvider, + PreviewProvider, + NewTabSearchProvider, + Preferences, + XPCOMUtils, + Task +*/ + +/* exported NewTabMessages */ + +"use strict"; + +const {utils: Cu} = Components; +Cu.import("resource://gre/modules/Preferences.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Task.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "PlacesProvider", + "resource:///modules/PlacesProvider.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "PreviewProvider", + "resource:///modules/PreviewProvider.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "NewTabPrefsProvider", + "resource:///modules/NewTabPrefsProvider.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "NewTabSearchProvider", + "resource:///modules/NewTabSearchProvider.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "NewTabWebChannel", + "resource:///modules/NewTabWebChannel.jsm"); + +this.EXPORTED_SYMBOLS = ["NewTabMessages"]; + +const PREF_ENABLED = "browser.newtabpage.remote"; +const CURRENT_ENGINE = "browser-search-engine-modified"; + +// Action names are from the content's perspective. in from chrome == out from content +// Maybe replace the ACTION objects by a bi-directional Map a bit later? +const ACTIONS = { + inboundActions: [ + "REQUEST_PREFS", + "REQUEST_THUMB", + "REQUEST_FRECENT", + "REQUEST_UISTRINGS", + "REQUEST_SEARCH_SUGGESTIONS", + "REQUEST_MANAGE_ENGINES", + "REQUEST_SEARCH_STATE", + "REQUEST_REMOVE_FORM_HISTORY", + "REQUEST_PERFORM_SEARCH", + "REQUEST_CYCLE_ENGINE", + ], + prefs: { + inPrefs: "REQUEST_PREFS", + outPrefs: "RECEIVE_PREFS", + }, + preview: { + inThumb: "REQUEST_THUMB", + outThumb: "RECEIVE_THUMB", + }, + links: { + inFrecent: "REQUEST_FRECENT", + outFrecent: "RECEIVE_FRECENT", + outPlacesChange: "RECEIVE_PLACES_CHANGE", + }, + search: { + inSearch: { + UIStrings: "REQUEST_UISTRINGS", + suggestions: "REQUEST_SEARCH_SUGGESTIONS", + manageEngines: "REQUEST_MANAGE_ENGINES", + state: "REQUEST_SEARCH_STATE", + removeFormHistory: "REQUEST_REMOVE_FORM_HISTORY", + performSearch: "REQUEST_PERFORM_SEARCH", + cycleEngine: "REQUEST_CYCLE_ENGINE" + }, + outSearch: { + UIStrings: "RECEIVE_UISTRINGS", + suggestions: "RECEIVE_SEARCH_SUGGESTIONS", + state: "RECEIVE_SEARCH_STATE", + currentEngine: "RECEIVE_CURRENT_ENGINE" + }, + } +}; + +let NewTabMessages = { + + _prefs: {}, + + /** NEWTAB EVENT HANDLERS **/ + + handleContentRequest(actionName, {data, target}) { + switch (actionName) { + case ACTIONS.prefs.inPrefs: + // Return to the originator all newtabpage prefs + let results = NewTabPrefsProvider.prefs.newtabPagePrefs; + NewTabWebChannel.send(ACTIONS.prefs.outPrefs, results, target); + break; + case ACTIONS.preview.inThumb: + // Return to the originator a preview URL + PreviewProvider.getThumbnail(data).then(imgData => { + NewTabWebChannel.send(ACTIONS.preview.outThumb, {url: data, imgData}, target); + }); + break; + case ACTIONS.links.inFrecent: + // Return to the originator the top frecent links + PlacesProvider.links.getLinks().then(links => { + NewTabWebChannel.send(ACTIONS.links.outFrecent, links, target); + }); + break; + case ACTIONS.search.inSearch.UIStrings: + // Return to the originator all search strings to display + let strings = NewTabSearchProvider.search.searchSuggestionUIStrings; + NewTabWebChannel.send(ACTIONS.search.outSearch.UIStrings, strings, target); + break; + case ACTIONS.search.inSearch.suggestions: + // Return to the originator all search suggestions + Task.spawn(function*() { + try { + let {engineName, searchString} = data; + let suggestions = yield NewTabSearchProvider.search.asyncGetSuggestions(engineName, searchString, target); + NewTabWebChannel.send(ACTIONS.search.outSearch.suggestions, suggestions, target); + } catch (e) { + Cu.reportError(e); + } + }); + break; + case ACTIONS.search.inSearch.manageEngines: + // Open about:preferences to manage search state + NewTabSearchProvider.search.manageEngines(target.browser); + break; + case ACTIONS.search.inSearch.state: + // Return the state of the search component (i.e current engine and visible engine details) + Task.spawn(function*() { + try { + let state = yield NewTabSearchProvider.search.asyncGetState(); + NewTabWebChannel.broadcast(ACTIONS.search.outSearch.state, state); + } catch (e) { + Cu.reportError(e); + } + }); + break; + case ACTIONS.search.inSearch.removeFormHistory: + // Remove a form history entry from the search component + let suggestion = data; + NewTabSearchProvider.search.removeFormHistory(target, suggestion); + break; + case ACTIONS.search.inSearch.performSearch: + // Perform a search + NewTabSearchProvider.search.asyncPerformSearch(target, data).catch(Cu.reportError); + break; + case ACTIONS.search.inSearch.cycleEngine: + // Set the new current engine + NewTabSearchProvider.search.asyncCycleEngine(data).catch(Cu.reportError); + break; + } + }, + + /* + * Broadcast places change to all open newtab pages + */ + handlePlacesChange(type, data) { + NewTabWebChannel.broadcast(ACTIONS.links.outPlacesChange, {type, data}); + }, + + /* + * Broadcast current engine has changed to all open newtab pages + */ + _handleCurrentEngineChange(name, value) { // jshint unused: false + let engine = value; + NewTabWebChannel.broadcast(ACTIONS.search.outSearch.currentEngine, engine); + }, + + /* + * Broadcast preference changes to all open newtab pages + */ + handlePrefChange(actionName, value) { + let prefChange = {}; + prefChange[actionName] = value; + NewTabWebChannel.broadcast(ACTIONS.prefs.outPrefs, prefChange); + }, + + _handleEnabledChange(prefName, value) { + if (prefName === PREF_ENABLED) { + if (this._prefs.enabled && !value) { + this.uninit(); + } else if (!this._prefs.enabled && value) { + this.init(); + } + } + }, + + init() { + this.handleContentRequest = this.handleContentRequest.bind(this); + this._handleEnabledChange = this._handleEnabledChange.bind(this); + this._handleCurrentEngineChange = this._handleCurrentEngineChange.bind(this); + + PlacesProvider.links.init(); + NewTabPrefsProvider.prefs.init(); + NewTabSearchProvider.search.init(); + NewTabWebChannel.init(); + + this._prefs.enabled = Preferences.get(PREF_ENABLED, false); + + if (this._prefs.enabled) { + for (let action of ACTIONS.inboundActions) { + NewTabWebChannel.on(action, this.handleContentRequest); + } + + NewTabPrefsProvider.prefs.on(PREF_ENABLED, this._handleEnabledChange); + NewTabSearchProvider.search.on(CURRENT_ENGINE, this._handleCurrentEngineChange); + + for (let pref of NewTabPrefsProvider.newtabPagePrefSet) { + NewTabPrefsProvider.prefs.on(pref, this.handlePrefChange); + } + + PlacesProvider.links.on("deleteURI", this.handlePlacesChange); + PlacesProvider.links.on("clearHistory", this.handlePlacesChange); + PlacesProvider.links.on("linkChanged", this.handlePlacesChange); + PlacesProvider.links.on("manyLinksChanged", this.handlePlacesChange); + } + }, + + uninit() { + this._prefs.enabled = Preferences.get(PREF_ENABLED, false); + + if (this._prefs.enabled) { + NewTabPrefsProvider.prefs.off(PREF_ENABLED, this._handleEnabledChange); + NewTabSearchProvider.search.off(CURRENT_ENGINE, this._handleCurrentEngineChange); + + for (let action of ACTIONS.inboundActions) { + NewTabWebChannel.off(action, this.handleContentRequest); + } + + for (let pref of NewTabPrefsProvider.newtabPagePrefSet) { + NewTabPrefsProvider.prefs.off(pref, this.handlePrefChange); + } + } + + NewTabPrefsProvider.prefs.uninit(); + NewTabSearchProvider.search.uninit(); + NewTabWebChannel.uninit(); + } +}; |