1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
|
// Copyright (c) 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';
/**
* @fileoverview This extension manages communications between Chrome,
* Google.com pages and the Chrome Hotword extension.
*
* This helper extension is required due to the depoyment plan for Chrome M34:
*
* - The hotword extension will be distributed as an externally loaded
* component extension.
* - Settings for enabling and disabling the hotword extension has moved to
* Chrome settings.
* - Newtab page is served via chrome://newtab/
*
*/
/** @constructor */
var OptInManager = function() {};
/**
* @const {string}
* @private
*/
OptInManager.HOTWORD_EXTENSION_ID_ = 'bepbmhgboaologfdajaanbcjmnhjmhfn';
/**
* Commands sent from the page to this content script.
* @enum {string}
*/
OptInManager.CommandFromPage = {
// User has explicitly clicked 'no'.
CLICKED_NO_OPTIN: 'hcno',
// User has opted in.
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, sendResponse, hotwordStatus) {
if (tab.incognito || !hotwordStatus.available) {
sendResponse({'doNotShowOptinMessage': true});
return;
}
if (!hotwordStatus.enabledSet) {
chrome.tabs.executeScript(tab.id, {'file': 'optin_client.js'});
sendResponse(hotwordStatus);
return;
}
if (hotwordStatus.enabled)
chrome.tabs.executeScript(tab.id, {'file': 'audio_client.js'});
sendResponse({'doNotShowOptinMessage': true});
};
/**
* Handles messages from the helper content script.
* @param {*} request Message from the sender.
* @param {MessageSender} sender Information about the 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) {
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);
chrome.hotwordPrivate.getStatus(
this.injectTab_.bind(this, sender.tab, sendResponse));
return true;
}
break;
// User has explicitly clicked 'no thanks'.
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 an eligible hotword URL.
*/
OptInManager.prototype.isEligibleUrl = function(url) {
if (!url)
return false;
// More URLs will be added in the future so leaving this as an array.
var baseUrls = [
'chrome://newtab'
];
var baseGoogleUrls = [
'https://www.google.',
'https://encrypted.google.'
];
var tlds = [
'com'
];
// 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() {
// 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));
chrome.runtime.onMessageExternal.addListener(
this.handleMessage_.bind(this));
};
new OptInManager().initialize();
|