/**
- * Commands sent from this helper extension to the hotword extension.
- * @enum {string}
- */
-OptInManager.CommandFromHelper = {
- DISABLE: 'ds',
- ENABLE: 'en'
-};
-
-
-/**
* Commands sent from the page to this content script.
* @enum {string}
*/
// User has explicitly clicked 'no'.
CLICKED_NO_OPTIN: 'hcno',
// User has opted in.
- CLICKED_OPTIN: 'hco'
-};
-
-
-/**
- * Handles a tab being activated / focused on.
- * @param {{tabId: number}} info Information about the activated tab.
- * @private
- */
-OptInManager.prototype.handleActivatedTab_ = function(info) {
- chrome.tabs.get(info.tabId, this.preInjectTab_.bind(this));
-};
-
-
-/**
- * Handles an updated tab.
- * @param {number} tabId Id of the updated tab.
- * @param {{status: string}} info Change info of the tab.
- * @param {!Tab} tab Updated tab.
- * @private
- */
-OptInManager.prototype.handleUpdatedTab_ = function(tabId, info, tab) {
- // Chrome fires multiple update events: undefined, loading and completed.
- // We perform content injection on loading state.
- if ('loading' !== info['status'])
- return;
- this.preInjectTab_(tab);
-};
-
-
-/**
- * @param {Tab} tab Tab to consider.
- * @private
- */
-OptInManager.prototype.preInjectTab_ = function(tab) {
- if (!tab || !this.isEligibleUrl(tab.url))
- return;
- if (chrome.hotwordPrivate && chrome.hotwordPrivate.getStatus)
- chrome.hotwordPrivate.getStatus(this.injectTab_.bind(this, tab));
+ CLICKED_OPTIN: 'hco',
+ // Audio logging is opted in.
+ AUDIO_LOGGING_ON: 'alon',
+ // Audio logging is opted out.
+ AUDIO_LOGGING_OFF: 'aloff',
+ // User visited an eligible page.
+ PAGE_WAKEUP: 'wu'
};
/**
* @param {Tab} tab Tab to inject.
+ * @param {function(HotwordStatus)} sendResponse Callback function to respond
+ * to sender.
* @param {HotwordStatus} hotwordStatus Status of the hotword extension.
* @private
*/
-OptInManager.prototype.injectTab_ = function(tab, hotwordStatus) {
- if (hotwordStatus.available) {
- if (hotwordStatus.enabled)
- chrome.tabs.executeScript(tab.id, {'file': 'audio_client.js'});
- else
- chrome.tabs.executeScript(tab.id, {'file': 'optin_client.js'});
+OptInManager.prototype.injectTab_ = function(
+ tab, sendResponse, hotwordStatus) {
+ if (tab.incognito) {
+ sendResponse({'doNotShowOptinMessage': true});
+ return;
}
-};
-
-
-/**
- * Handles changes in the enabled state of the hotword feature in the
- * Chrome settings page.
- * @private
- */
-OptInManager.prototype.handleEnabledChange_ = function() {
- if (chrome.hotwordPrivate && chrome.hotwordPrivate.getStatus)
- chrome.hotwordPrivate.getStatus(this.updateEnabled_.bind(this));
-};
-
-/**
- * Sends a message to the hotword extension to update it about Chrome settings.
- * @param {HotwordStatus} hotwordStatus Status of the hotword extension.
- * @private
- */
-OptInManager.prototype.updateEnabled_ = function(hotwordStatus) {
- if (hotwordStatus.enabled) {
- chrome.runtime.sendMessage(
- OptInManager.HOTWORD_EXTENSION_ID_,
- {'cmd': OptInManager.CommandFromHelper.ENABLE});
- } else {
- chrome.runtime.sendMessage(
- OptInManager.HOTWORD_EXTENSION_ID_,
- {'cmd': OptInManager.CommandFromHelper.DISABLE});
- }
+ if (!hotwordStatus.available)
+ return;
+ if (hotwordStatus.enabled)
+ chrome.tabs.executeScript(tab.id, {'file': 'audio_client.js'});
+ else if (!hotwordStatus.enabledSet)
+ chrome.tabs.executeScript(tab.id, {'file': 'optin_client.js'});
+ sendResponse(hotwordStatus);
};
* Handles messages from the helper content script.
* @param {*} request Message from the sender.
* @param {MessageSender} sender Information about the sender.
- * @param {function(*)} sendResponse Callback function to respond to sender.
+ * @param {function(HotwordStatus)} sendResponse Callback function to respond
+ * to sender.
+ * @return {boolean} Whether to maintain the port open to call sendResponse.
* @private
*/
OptInManager.prototype.handleMessage_ = function(
request, sender, sendResponse) {
- if (request.type) {
- if (request.type === OptInManager.CommandFromPage.CLICKED_OPTIN) {
- if (chrome.hotwordPrivate && chrome.hotwordPrivate.setEnabled) {
+ switch (request.type) {
+ case OptInManager.CommandFromPage.PAGE_WAKEUP:
+ if (((sender.tab && this.isEligibleUrl(sender.tab.url)) ||
+ sender.id == OptInManager.HOTWORD_EXTENSION_ID_) &&
+ chrome.hotwordPrivate && chrome.hotwordPrivate.getStatus) {
+ chrome.hotwordPrivate.getStatus(
+ this.injectTab_.bind(this, request.tab || sender.tab,
+ sendResponse));
+ return true;
+ }
+ break;
+ case OptInManager.CommandFromPage.CLICKED_OPTIN:
+ if (chrome.hotwordPrivate && chrome.hotwordPrivate.setEnabled &&
+ chrome.hotwordPrivate.getStatus) {
chrome.hotwordPrivate.setEnabled(true);
- this.preInjectTab_(sender.tab);
+ chrome.hotwordPrivate.getStatus(
+ this.injectTab_.bind(this, sender.tab, sendResponse));
+ return true;
}
- }
+ break;
// User has explicitly clicked 'no thanks'.
- if (request.type === OptInManager.CommandFromPage.CLICKED_NO_OPTIN) {
+ case OptInManager.CommandFromPage.CLICKED_NO_OPTIN:
if (chrome.hotwordPrivate && chrome.hotwordPrivate.setEnabled) {
chrome.hotwordPrivate.setEnabled(false);
}
- }
+ break;
+ // Information regarding the audio logging preference was sent.
+ case OptInManager.CommandFromPage.AUDIO_LOGGING_ON:
+ if (chrome.hotwordPrivate &&
+ chrome.hotwordPrivate.setAudioLoggingEnabled) {
+ chrome.hotwordPrivate.setAudioLoggingEnabled(true);
+ }
+ break;
+ case OptInManager.CommandFromPage.AUDIO_LOGGING_OFF:
+ if (chrome.hotwordPrivate &&
+ chrome.hotwordPrivate.setAudioLoggingEnabled) {
+ chrome.hotwordPrivate.setAudioLoggingEnabled(false);
+ }
+ break;
+ default:
+ break;
}
+ return false;
};
+/**
+ * Helper function to test URLs as being valid for running the
+ * hotwording extension. It's used by isEligibleUrl to make that
+ * function clearer.
+ * @param {string} url URL to check.
+ * @param {string} base Base URL to compare against..
+ * @return {boolean} True if url is an eligible hotword URL.
+ */
+OptInManager.prototype.checkEligibleUrl = function(url, base) {
+ if (!url)
+ return false;
+
+ if (url === base ||
+ url === base + '/' ||
+ url.indexOf(base + '/_/chrome/newtab?') === 0 || // Appcache NTP.
+ url.indexOf(base + '/?') === 0 ||
+ url.indexOf(base + '/#') === 0 ||
+ url.indexOf(base + '/webhp') === 0 ||
+ url.indexOf(base + '/search') === 0) {
+ return true;
+ }
+ return false;
+
+};
/**
* Determines if a URL is eligible for hotwording. For now, the
* valid pages are the Google HP and SERP (this will include the NTP).
- * @param {string} url Url to check.
- * @return {boolean} True if url is eligible hotword url.
+ * @param {string} url URL to check.
+ * @return {boolean} True if url is an eligible hotword URL.
*/
OptInManager.prototype.isEligibleUrl = function(url) {
- if (!url) {
+ if (!url)
return false;
- }
+ // More URLs will be added in the future so leaving this as an array.
var baseUrls = [
- 'https://www.google.com',
- 'chrome://newtab',
- 'https://encrypted.google.com'
+ 'chrome://newtab'
+ ];
+ var baseGoogleUrls = [
+ 'https://www.google.',
+ 'https://encrypted.google.'
+ ];
+ var tlds = [
+ 'com',
+ 'co.uk',
+ 'de',
+ 'fr',
+ 'ru'
];
- for (var i = 0; i < baseUrls.length; i++) {
- var base = baseUrls[i];
- if (url === base + '/' ||
- url.indexOf(base + '/_/chrome/newtab?') === 0 || // Appcache NTP.
- url.indexOf(base + '/?') === 0 ||
- url.indexOf(base + '/#') === 0 ||
- url.indexOf(base + '/webhp') === 0 ||
- url.indexOf(base + '/search') === 0) {
- return true;
+ // Check URLs which do not have locale-based TLDs first.
+ if (this.checkEligibleUrl(url, baseUrls[0]))
+ return true;
+
+ // Check URLs with each type of local-based TLD.
+ for (var i = 0; i < baseGoogleUrls.length; i++) {
+ for (var j = 0; j < tlds.length; j++) {
+ var base = baseGoogleUrls[i] + tlds[j];
+ if (this.checkEligibleUrl(url, base))
+ return true;
}
}
return false;
* Initializes the extension.
*/
OptInManager.prototype.initialize = function() {
- chrome.tabs.onActivated.addListener(this.handleActivatedTab_.bind(this));
- chrome.tabs.onUpdated.addListener(this.handleUpdatedTab_.bind(this));
+ // TODO(rlp): Possibly remove the next line. It's proably not used, but
+ // leaving for now to be safe. We should remove it once all messsage
+ // relaying is removed form the content scripts.
chrome.runtime.onMessage.addListener(this.handleMessage_.bind(this));
-
- if (chrome.hotwordPrivate && chrome.hotwordPrivate.onEnabledChanged) {
- chrome.hotwordPrivate.onEnabledChanged.addListener(
- this.handleEnabledChange_.bind(this));
- }
+ chrome.runtime.onMessageExternal.addListener(
+ this.handleMessage_.bind(this));
};