Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / resources / hotword_helper / manager.js
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.
4
5 'use strict';
6
7 /**
8  * @fileoverview This extension manages communications between Chrome,
9  * Google.com pages and the Chrome Hotword extension.
10  *
11  * This helper extension is required due to the depoyment plan for Chrome M34:
12  *
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
16  *      Chrome settings.
17  *  - Newtab page is served via chrome://newtab/
18  *
19  */
20
21
22
23 /** @constructor */
24 var OptInManager = function() {};
25
26
27 /**
28  * @const {string}
29  * @private
30  */
31 OptInManager.HOTWORD_EXTENSION_ID_ = 'bepbmhgboaologfdajaanbcjmnhjmhfn';
32
33
34 /**
35  * Test extension ID.
36  * @const {string}
37  * @private
38  */
39 OptInManager.TEST_EXTENSION_ID_ = 'cpfhkdbjfdgdebcjlifoldbijinjfifp';
40
41
42 /**
43  * Commands sent from the page to this content script.
44  * @enum {string}
45  */
46 OptInManager.CommandFromPage = {
47   // User has explicitly clicked 'no'.
48   CLICKED_NO_OPTIN: 'hcno',
49   // User has opted in.
50   CLICKED_OPTIN: 'hco',
51   // Audio logging is opted in.
52   AUDIO_LOGGING_ON: 'alon',
53   // Audio logging is opted out.
54   AUDIO_LOGGING_OFF: 'aloff',
55   // User visited an eligible page.
56   PAGE_WAKEUP: 'wu'
57 };
58
59
60 /**
61  * @param {Tab} tab Tab to inject.
62  * @param {function(HotwordStatus)} sendResponse Callback function to respond
63  *     to sender.
64  * @param {HotwordStatus} hotwordStatus Status of the hotword extension.
65  * @private
66  */
67 OptInManager.prototype.injectTab_ = function(
68     tab, sendResponse, hotwordStatus) {
69   var response = {'doNotShowOptinMessage': true};
70
71   if (!tab.incognito && hotwordStatus.available) {
72     if (!hotwordStatus.enabledSet)
73       response = hotwordStatus;
74     else if (hotwordStatus.enabled)
75       chrome.tabs.executeScript(tab.id, {'file': 'audio_client.js'});
76   }
77
78   try {
79     sendResponse(response);
80   } catch (err) {
81     // Suppress the exception thrown by sendResponse() when the page doesn't
82     // specify a response callback in the call to chrome.runtime.sendMessage().
83     // Unfortunately, there doesn't appear to be a way to detect one-way
84     // messages without explicitly saying in the message itself.  This message
85     // is defined as a constant in extensions/renderer/messaging_bindings.cc
86     if (err.message == 'Attempting to use a disconnected port object')
87       return;
88     throw err;
89   }
90 };
91
92
93 /**
94  * Handles messages from the helper content script.
95  * @param {*} request Message from the sender.
96  * @param {MessageSender} sender Information about the sender.
97  * @param {function(HotwordStatus)} sendResponse Callback function to respond
98  *     to sender.
99  * @return {boolean} Whether to maintain the port open to call sendResponse.
100  * @private
101  */
102 OptInManager.prototype.handleMessage_ = function(
103     request, sender, sendResponse) {
104   switch (request.type) {
105     case OptInManager.CommandFromPage.PAGE_WAKEUP:
106       if (((sender.tab && this.isEligibleUrl(sender.tab.url)) ||
107           sender.id == OptInManager.HOTWORD_EXTENSION_ID_ ||
108           sender.id == OptInManager.TEST_EXTENSION_ID_) &&
109           chrome.hotwordPrivate && chrome.hotwordPrivate.getStatus) {
110         chrome.hotwordPrivate.getStatus(
111             this.injectTab_.bind(
112                 this,
113                 request.tab || sender.tab || {incognito: true},
114                 sendResponse));
115         return true;
116       }
117       break;
118     case OptInManager.CommandFromPage.CLICKED_OPTIN:
119       if (chrome.hotwordPrivate && chrome.hotwordPrivate.setEnabled &&
120           chrome.hotwordPrivate.getStatus) {
121         chrome.hotwordPrivate.setEnabled(true);
122         chrome.hotwordPrivate.getStatus(
123             this.injectTab_.bind(this, sender.tab, sendResponse));
124         return true;
125       }
126       break;
127     // User has explicitly clicked 'no thanks'.
128     case OptInManager.CommandFromPage.CLICKED_NO_OPTIN:
129       if (chrome.hotwordPrivate && chrome.hotwordPrivate.setEnabled) {
130         chrome.hotwordPrivate.setEnabled(false);
131       }
132       break;
133     // Information regarding the audio logging preference was sent.
134     case OptInManager.CommandFromPage.AUDIO_LOGGING_ON:
135       if (chrome.hotwordPrivate &&
136           chrome.hotwordPrivate.setAudioLoggingEnabled) {
137         chrome.hotwordPrivate.setAudioLoggingEnabled(true);
138       }
139       break;
140     case OptInManager.CommandFromPage.AUDIO_LOGGING_OFF:
141       if (chrome.hotwordPrivate &&
142           chrome.hotwordPrivate.setAudioLoggingEnabled) {
143         chrome.hotwordPrivate.setAudioLoggingEnabled(false);
144       }
145       break;
146     default:
147       break;
148   }
149   return false;
150 };
151
152 /**
153  * Helper function to test URLs as being valid for running the
154  * hotwording extension. It's used by isEligibleUrl to make that
155  * function clearer.
156  * @param {string} url URL to check.
157  * @param {string} base Base URL to compare against..
158  * @return {boolean} True if url is an eligible hotword URL.
159  */
160 OptInManager.prototype.checkEligibleUrl = function(url, base) {
161   if (!url)
162     return false;
163
164   if (url === base ||
165       url === base + '/' ||
166       url.indexOf(base + '/_/chrome/newtab?') === 0 ||  // Appcache NTP.
167       url.indexOf(base + '/?') === 0 ||
168       url.indexOf(base + '/#') === 0 ||
169       url.indexOf(base + '/webhp') === 0 ||
170       url.indexOf(base + '/search') === 0) {
171     return true;
172   }
173   return false;
174
175 };
176
177 /**
178  * Determines if a URL is eligible for hotwording. For now, the
179  * valid pages are the Google HP and SERP (this will include the NTP).
180  * @param {string} url URL to check.
181  * @return {boolean} True if url is an eligible hotword URL.
182  */
183 OptInManager.prototype.isEligibleUrl = function(url) {
184   if (!url)
185     return false;
186
187   // More URLs will be added in the future so leaving this as an array.
188   var baseUrls = [
189     'chrome://newtab'
190   ];
191   var baseGoogleUrls = [
192     'https://www.google.',
193     'https://encrypted.google.'
194   ];
195   var tlds = [
196     'com',
197     'co.uk',
198     'de',
199     'fr',
200     'ru'
201   ];
202
203   // Check URLs which do not have locale-based TLDs first.
204   if (this.checkEligibleUrl(url, baseUrls[0]))
205     return true;
206
207   // Check URLs with each type of local-based TLD.
208   for (var i = 0; i < baseGoogleUrls.length; i++) {
209     for (var j = 0; j < tlds.length; j++) {
210       var base = baseGoogleUrls[i] + tlds[j];
211       if (this.checkEligibleUrl(url, base))
212         return true;
213     }
214   }
215   return false;
216 };
217
218
219 /**
220  * Initializes the extension.
221  */
222 OptInManager.prototype.initialize = function() {
223   // TODO(rlp): Possibly remove the next line. It's proably not used, but
224   // leaving for now to be safe. We should remove it once all messsage
225   // relaying is removed form the content scripts.
226   chrome.runtime.onMessage.addListener(this.handleMessage_.bind(this));
227   chrome.runtime.onMessageExternal.addListener(
228       this.handleMessage_.bind(this));
229 };
230
231
232 new OptInManager().initialize();