1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
8 * @fileoverview This extension manages communications between Chrome,
9 * Google.com pages and the Chrome Hotword extension.
11 * This helper extension is required due to the depoyment plan for Chrome M34:
13 * - The hotword extension will be distributed as an externally loaded
14 * component extension.
15 * - Settings for enabling and disabling the hotword extension has moved to
17 * - Newtab page is served via chrome://newtab/
24 var OptInManager = function() {};
31 OptInManager
.HOTWORD_EXTENSION_ID_
= 'bepbmhgboaologfdajaanbcjmnhjmhfn';
35 * Commands sent from this helper extension to the hotword extension.
38 OptInManager
.CommandFromHelper
= {
45 * Commands sent from the page to this content script.
48 OptInManager
.CommandFromPage
= {
49 // User has explicitly clicked 'no'.
50 CLICKED_NO_OPTIN
: 'hcno',
57 * Handles a tab being activated / focused on.
58 * @param {{tabId: number}} info Information about the activated tab.
61 OptInManager
.prototype.handleActivatedTab_ = function(info
) {
62 chrome
.tabs
.get(info
.tabId
, this.preInjectTab_
.bind(this));
67 * Handles an updated tab.
68 * @param {number} tabId Id of the updated tab.
69 * @param {{status: string}} info Change info of the tab.
70 * @param {!Tab} tab Updated tab.
73 OptInManager
.prototype.handleUpdatedTab_ = function(tabId
, info
, tab
) {
74 // Chrome fires multiple update events: undefined, loading and completed.
75 // We perform content injection on loading state.
76 if ('loading' !== info
['status'])
78 this.preInjectTab_(tab
);
83 * @param {Tab} tab Tab to consider.
86 OptInManager
.prototype.preInjectTab_ = function(tab
) {
87 if (!tab
|| !this.isEligibleUrl(tab
.url
))
89 if (chrome
.hotwordPrivate
&& chrome
.hotwordPrivate
.getStatus
)
90 chrome
.hotwordPrivate
.getStatus(this.injectTab_
.bind(this, tab
));
95 * @param {Tab} tab Tab to inject.
96 * @param {HotwordStatus} hotwordStatus Status of the hotword extension.
99 OptInManager
.prototype.injectTab_ = function(tab
, hotwordStatus
) {
100 if (hotwordStatus
.available
) {
101 if (hotwordStatus
.enabled
)
102 chrome
.tabs
.executeScript(tab
.id
, {'file': 'audio_client.js'});
104 chrome
.tabs
.executeScript(tab
.id
, {'file': 'optin_client.js'});
110 * Handles changes in the enabled state of the hotword feature in the
111 * Chrome settings page.
114 OptInManager
.prototype.handleEnabledChange_ = function() {
115 if (chrome
.hotwordPrivate
&& chrome
.hotwordPrivate
.getStatus
)
116 chrome
.hotwordPrivate
.getStatus(this.updateEnabled_
.bind(this));
121 * Sends a message to the hotword extension to update it about Chrome settings.
122 * @param {HotwordStatus} hotwordStatus Status of the hotword extension.
125 OptInManager
.prototype.updateEnabled_ = function(hotwordStatus
) {
126 if (hotwordStatus
.enabled
) {
127 chrome
.runtime
.sendMessage(
128 OptInManager
.HOTWORD_EXTENSION_ID_
,
129 {'cmd': OptInManager
.CommandFromHelper
.ENABLE
});
131 chrome
.runtime
.sendMessage(
132 OptInManager
.HOTWORD_EXTENSION_ID_
,
133 {'cmd': OptInManager
.CommandFromHelper
.DISABLE
});
139 * Handles messages from the helper content script.
140 * @param {*} request Message from the sender.
141 * @param {MessageSender} sender Information about the sender.
142 * @param {function(*)} sendResponse Callback function to respond to sender.
145 OptInManager
.prototype.handleMessage_ = function(
146 request
, sender
, sendResponse
) {
148 if (request
.type
=== OptInManager
.CommandFromPage
.CLICKED_OPTIN
) {
149 if (chrome
.hotwordPrivate
&& chrome
.hotwordPrivate
.setEnabled
) {
150 chrome
.hotwordPrivate
.setEnabled(true);
151 this.preInjectTab_(sender
.tab
);
154 // User has explicitly clicked 'no thanks'.
155 if (request
.type
=== OptInManager
.CommandFromPage
.CLICKED_NO_OPTIN
) {
156 if (chrome
.hotwordPrivate
&& chrome
.hotwordPrivate
.setEnabled
) {
157 chrome
.hotwordPrivate
.setEnabled(false);
165 * Determines if a URL is eligible for hotwording. For now, the
166 * valid pages are the Google HP and SERP (this will include the NTP).
167 * @param {string} url Url to check.
168 * @return {boolean} True if url is eligible hotword url.
170 OptInManager
.prototype.isEligibleUrl = function(url
) {
176 'https://www.google.com',
178 'https://encrypted.google.com'
181 for (var i
= 0; i
< baseUrls
.length
; i
++) {
182 var base
= baseUrls
[i
];
183 if (url
=== base
+ '/' ||
184 url
.indexOf(base
+ '/_/chrome/newtab?') === 0 || // Appcache NTP.
185 url
.indexOf(base
+ '/?') === 0 ||
186 url
.indexOf(base
+ '/#') === 0 ||
187 url
.indexOf(base
+ '/webhp') === 0 ||
188 url
.indexOf(base
+ '/search') === 0) {
197 * Initializes the extension.
199 OptInManager
.prototype.initialize = function() {
200 chrome
.tabs
.onActivated
.addListener(this.handleActivatedTab_
.bind(this));
201 chrome
.tabs
.onUpdated
.addListener(this.handleUpdatedTab_
.bind(this));
202 chrome
.runtime
.onMessage
.addListener(this.handleMessage_
.bind(this));
204 if (chrome
.hotwordPrivate
&& chrome
.hotwordPrivate
.onEnabledChanged
) {
205 chrome
.hotwordPrivate
.onEnabledChanged
.addListener(
206 this.handleEnabledChange_
.bind(this));
211 new OptInManager().initialize();