OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 (function() { | 5 (function() { |
6 'use strict'; | 6 'use strict'; |
7 | 7 |
8 cr.define('cr.translateInternals', function() { | 8 cr.define('cr.translateInternals', function() { |
9 | 9 |
10 var detectionLogs = []; | 10 var detectionLogs = []; |
11 | 11 |
12 /** | 12 /** |
13 * Initializes UI and sends a message to the browser for | 13 * Initializes UI and sends a message to the browser for |
14 * initialization. | 14 * initialization. |
15 */ | 15 */ |
16 function initialize() { | 16 function initialize() { |
17 cr.ui.decorate('tabbox', cr.ui.TabBox); | 17 cr.ui.decorate('tabbox', cr.ui.TabBox); |
18 chrome.send('requestInfo'); | 18 chrome.send('requestInfo'); |
19 | 19 |
20 var button = $('detection-logs-dump'); | 20 var button = $('detection-logs-dump'); |
21 button.addEventListener('click', onDetectionLogsDump); | 21 button.addEventListener('click', onDetectionLogsDump); |
22 | 22 |
23 var tabpanelNodeList = document.getElementsByTagName('tabpanel'); | 23 var tabpanelNodeList = document.getElementsByTagName('tabpanel'); |
24 var tabpanels = Array.prototype.slice.call(tabpanelNodeList, 0); | 24 var tabpanels = Array.prototype.slice.call(tabpanelNodeList, 0); |
25 var tabpanelIds = tabpanels.map(function(tab) { | 25 var tabpanelIds = tabpanels.map(function(tab) { |
26 return tab.id; | 26 return tab.id; |
| 27 }); |
| 28 |
| 29 var tabNodeList = document.getElementsByTagName('tab'); |
| 30 var tabs = Array.prototype.slice.call(tabNodeList, 0); |
| 31 tabs.forEach(function(tab) { |
| 32 tab.onclick = function(e) { |
| 33 var tabbox = document.querySelector('tabbox'); |
| 34 var tabpanel = tabpanels[tabbox.selectedIndex]; |
| 35 var hash = tabpanel.id.match(/(?:^tabpanel-)(.+)/)[1]; |
| 36 window.location.hash = hash; |
| 37 }; |
| 38 }); |
| 39 |
| 40 var activateTabByHash = function() { |
| 41 var hash = window.location.hash; |
| 42 |
| 43 // Remove the first character '#'. |
| 44 hash = hash.substring(1); |
| 45 |
| 46 var id = 'tabpanel-' + hash; |
| 47 if (tabpanelIds.indexOf(id) == -1) |
| 48 return; |
| 49 |
| 50 $(id).selected = true; |
| 51 }; |
| 52 |
| 53 window.onhashchange = activateTabByHash; |
| 54 activateTabByHash(); |
| 55 } |
| 56 |
| 57 /* |
| 58 * Creates a button to dismiss an item. |
| 59 * |
| 60 * @param {Function} func Callback called when the button is clicked. |
| 61 */ |
| 62 function createDismissingButton(func) { |
| 63 var button = document.createElement('button'); |
| 64 button.textContent = 'X'; |
| 65 button.classList.add('dismissing'); |
| 66 button.addEventListener('click', function(e) { |
| 67 e.preventDefault(); |
| 68 func(); |
| 69 }, false); |
| 70 return button; |
| 71 } |
| 72 |
| 73 /** |
| 74 * Creates a new LI element with a button to dismiss the item. |
| 75 * |
| 76 * @param {string} text The lable of the LI element. |
| 77 * @param {Function} func Callback called when the button is clicked. |
| 78 */ |
| 79 function createLIWithDismissingButton(text, func) { |
| 80 var span = document.createElement('span'); |
| 81 span.textContent = text; |
| 82 |
| 83 var li = document.createElement('li'); |
| 84 li.appendChild(span); |
| 85 li.appendChild(createDismissingButton(func)); |
| 86 return li; |
| 87 } |
| 88 |
| 89 /** |
| 90 * Formats the language name to a human-readable text. For example, if |
| 91 * |langCode| is 'en', this may return 'en (English)'. |
| 92 * |
| 93 * @param {string} langCode ISO 639 language code. |
| 94 * @return {string} The formatted string. |
| 95 */ |
| 96 function formatLanguageCode(langCode) { |
| 97 var key = 'language-' + langCode; |
| 98 if (loadTimeData.valueExists(key)) { |
| 99 var langName = loadTimeData.getString(key); |
| 100 return langCode + ' (' + langName + ')'; |
| 101 } |
| 102 |
| 103 return langCode; |
| 104 } |
| 105 |
| 106 /** |
| 107 * Formats the error type to a human-readable text. |
| 108 * |
| 109 * @param {string} error Translation error type from the browser. |
| 110 * @return {string} The formatted string. |
| 111 */ |
| 112 function formatTranslateErrorsType(error) { |
| 113 // This list is from chrome/common/translate/translate_errors.h. |
| 114 // If this header file is updated, the below list also should be updated. |
| 115 var errorStrs = { |
| 116 0: 'None', |
| 117 1: 'Network', |
| 118 2: 'Initialization Error', |
| 119 3: 'Unknown Language', |
| 120 4: 'Unsupported Language', |
| 121 5: 'Identical Languages', |
| 122 6: 'Translation Error', |
| 123 7: 'Translation Timeout', |
| 124 8: 'Unexpected Script Error', |
| 125 9: 'Bad Origin', |
| 126 10: 'Script Load Error', |
| 127 }; |
| 128 |
| 129 if (error < 0 || errorStrs.length <= error) { |
| 130 console.error('Invalid error code:', error); |
| 131 return 'Invalid Error Code'; |
| 132 } |
| 133 return errorStrs[error]; |
| 134 } |
| 135 |
| 136 /** |
| 137 * Handles the message of 'prefsUpdated' from the browser. |
| 138 * |
| 139 * @param {Object} detail the object which represents pref values. |
| 140 */ |
| 141 function onPrefsUpdated(detail) { |
| 142 var ul; |
| 143 |
| 144 ul = document.querySelector('#prefs-blocked-languages ul'); |
| 145 ul.innerHTML = ''; |
| 146 |
| 147 if ('translate_blocked_languages' in detail) { |
| 148 var langs = detail['translate_blocked_languages']; |
| 149 |
| 150 langs.forEach(function(langCode) { |
| 151 var text = formatLanguageCode(langCode); |
| 152 |
| 153 var li = createLIWithDismissingButton(text, function() { |
| 154 chrome.send('removePrefItem', ['blocked_languages', langCode]); |
| 155 }); |
| 156 ul.appendChild(li); |
27 }); | 157 }); |
28 | 158 } |
29 var tabNodeList = document.getElementsByTagName('tab'); | 159 |
30 var tabs = Array.prototype.slice.call(tabNodeList, 0); | 160 ul = document.querySelector('#prefs-language-blacklist ul'); |
31 tabs.forEach(function(tab) { | 161 ul.innerHTML = ''; |
32 tab.onclick = function(e) { | 162 |
33 var tabbox = document.querySelector('tabbox'); | 163 if ('translate_language_blacklist' in detail) { |
34 var tabpanel = tabpanels[tabbox.selectedIndex]; | 164 var langs = detail['translate_language_blacklist']; |
35 var hash = tabpanel.id.match(/(?:^tabpanel-)(.+)/)[1]; | 165 |
36 window.location.hash = hash; | 166 langs.forEach(function(langCode) { |
37 }; | 167 var text = formatLanguageCode(langCode); |
| 168 |
| 169 var li = createLIWithDismissingButton(text, function() { |
| 170 chrome.send('removePrefItem', ['language_blacklist', langCode]); |
| 171 }); |
| 172 ul.appendChild(li); |
38 }); | 173 }); |
39 | 174 } |
40 var activateTabByHash = function() { | 175 |
41 var hash = window.location.hash; | 176 ul = document.querySelector('#prefs-site-blacklist ul'); |
42 | 177 ul.innerHTML = ''; |
43 // Remove the first character '#'. | 178 |
44 hash = hash.substring(1); | 179 if ('translate_site_blacklist' in detail) { |
45 | 180 var sites = detail['translate_site_blacklist']; |
46 var id = 'tabpanel-' + hash; | 181 |
47 if (tabpanelIds.indexOf(id) == -1) | 182 sites.forEach(function(site) { |
48 return; | 183 var li = createLIWithDismissingButton(site, function() { |
49 | 184 chrome.send('removePrefItem', ['site_blacklist', site]); |
50 $(id).selected = true; | 185 }); |
51 }; | 186 ul.appendChild(li); |
52 | 187 }); |
53 window.onhashchange = activateTabByHash; | 188 } |
54 activateTabByHash(); | 189 |
55 } | 190 ul = document.querySelector('#prefs-whitelists ul'); |
56 | 191 ul.innerHTML = ''; |
57 /* | 192 |
58 * Creates a button to dismiss an item. | 193 if ('translate_whitelists' in detail) { |
59 * | 194 var pairs = detail['translate_whitelists']; |
60 * @param {Function} func Callback called when the button is clicked. | 195 |
61 */ | 196 Object.keys(pairs).forEach(function(fromLangCode) { |
62 function createDismissingButton(func) { | 197 var toLangCode = pairs[fromLangCode]; |
| 198 var text = formatLanguageCode(fromLangCode) + ' \u2192 ' + |
| 199 formatLanguageCode(toLangCode); |
| 200 |
| 201 var li = createLIWithDismissingButton(text, function() { |
| 202 chrome.send( |
| 203 'removePrefItem', ['whitelists', fromLangCode, toLangCode]); |
| 204 }); |
| 205 ul.appendChild(li); |
| 206 }); |
| 207 } |
| 208 |
| 209 var p = $('prefs-too-often-denied'); |
| 210 p.classList.toggle( |
| 211 'prefs-setting-disabled', !detail['translate_too_often_denied']); |
| 212 p.appendChild(createDismissingButton( |
| 213 chrome.send.bind(null, 'removePrefItem', ['too_often_denied']))); |
| 214 |
| 215 p = document.querySelector('#prefs-dump p'); |
| 216 var content = JSON.stringify(detail, null, 2); |
| 217 p.textContent = content; |
| 218 } |
| 219 |
| 220 /** |
| 221 * Handles the message of 'supportedLanguagesUpdated' from the browser. |
| 222 * |
| 223 * @param {Object} details the object which represents the supported |
| 224 * languages by the Translate server. |
| 225 */ |
| 226 function onSupportedLanguagesUpdated(details) { |
| 227 var span = |
| 228 $('prefs-supported-languages-last-updated').querySelector('span'); |
| 229 span.textContent = formatDate(new Date(details['last_updated'])); |
| 230 |
| 231 var ul = $('prefs-supported-languages-languages'); |
| 232 ul.innerHTML = ''; |
| 233 var languages = details['languages']; |
| 234 for (var i = 0; i < languages.length; i++) { |
| 235 var language = languages[i]; |
| 236 var li = document.createElement('li'); |
| 237 |
| 238 var text = formatLanguageCode(language); |
| 239 li.innerText = text; |
| 240 |
| 241 ul.appendChild(li); |
| 242 } |
| 243 } |
| 244 |
| 245 /** |
| 246 * Handles the message of 'countryUpdated' from the browser. |
| 247 * |
| 248 * @param {Object} details the object containing the country |
| 249 * information. |
| 250 */ |
| 251 function onCountryUpdated(details) { |
| 252 var p; |
| 253 p = $('country-override'); |
| 254 |
| 255 p.innerHTML = ''; |
| 256 |
| 257 if ('country' in details) { |
| 258 var country = details['country']; |
| 259 |
| 260 var h2 = $('override-variations-country'); |
| 261 h2.title = |
| 262 ('Changing this value will override the permanent country stored ' + |
| 263 'by variations. Normally, this value gets automatically updated ' + |
| 264 'with a new value received from the variations server when ' + |
| 265 'Chrome is updated.'); |
| 266 |
| 267 var input = document.createElement('input'); |
| 268 input.type = 'text'; |
| 269 input.value = country; |
| 270 |
63 var button = document.createElement('button'); | 271 var button = document.createElement('button'); |
64 button.textContent = 'X'; | 272 button.textContent = 'update'; |
65 button.classList.add('dismissing'); | 273 button.addEventListener('click', function() { |
66 button.addEventListener('click', function(e) { | 274 chrome.send('overrideCountry', [input.value]); |
67 e.preventDefault(); | |
68 func(); | |
69 }, false); | 275 }, false); |
70 return button; | 276 p.appendChild(input); |
71 } | 277 p.appendChild(document.createElement('br')); |
72 | 278 p.appendChild(button); |
73 /** | 279 |
74 * Creates a new LI element with a button to dismiss the item. | 280 if ('update' in details && details['update']) { |
75 * | 281 var div1 = document.createElement('div'); |
76 * @param {string} text The lable of the LI element. | 282 div1.textContent = 'Permanent stored country updated.'; |
77 * @param {Function} func Callback called when the button is clicked. | 283 var div2 = document.createElement('div'); |
78 */ | 284 div2.textContent = |
79 function createLIWithDismissingButton(text, func) { | 285 ('You will need to restart your browser ' + |
80 var span = document.createElement('span'); | 286 'for the changes to take effect.'); |
81 span.textContent = text; | 287 p.appendChild(div1); |
82 | 288 p.appendChild(div2); |
83 var li = document.createElement('li'); | |
84 li.appendChild(span); | |
85 li.appendChild(createDismissingButton(func)); | |
86 return li; | |
87 } | |
88 | |
89 /** | |
90 * Formats the language name to a human-readable text. For example, if | |
91 * |langCode| is 'en', this may return 'en (English)'. | |
92 * | |
93 * @param {string} langCode ISO 639 language code. | |
94 * @return {string} The formatted string. | |
95 */ | |
96 function formatLanguageCode(langCode) { | |
97 var key = 'language-' + langCode; | |
98 if (loadTimeData.valueExists(key)) { | |
99 var langName = loadTimeData.getString(key); | |
100 return langCode + ' (' + langName + ')'; | |
101 } | 289 } |
102 | 290 } else { |
103 return langCode; | 291 p.textContent = 'Could not load country info from Variations.'; |
104 } | 292 } |
105 | 293 } |
106 /** | 294 |
107 * Formats the error type to a human-readable text. | 295 /** |
108 * | 296 * Adds '0's to |number| as a string. |width| is length of the string |
109 * @param {string} error Translation error type from the browser. | 297 * including '0's. |
110 * @return {string} The formatted string. | 298 * |
111 */ | 299 * @param {string} number The number to be converted into a string. |
112 function formatTranslateErrorsType(error) { | 300 * @param {number} width The width of the returned string. |
113 // This list is from chrome/common/translate/translate_errors.h. | 301 * @return {string} The formatted string. |
114 // If this header file is updated, the below list also should be updated. | 302 */ |
115 var errorStrs = { | 303 function padWithZeros(number, width) { |
116 0: 'None', | 304 var numberStr = number.toString(); |
117 1: 'Network', | 305 var restWidth = width - numberStr.length; |
118 2: 'Initialization Error', | 306 if (restWidth <= 0) |
119 3: 'Unknown Language', | 307 return numberStr; |
120 4: 'Unsupported Language', | 308 |
121 5: 'Identical Languages', | 309 return Array(restWidth + 1).join('0') + numberStr; |
122 6: 'Translation Error', | 310 } |
123 7: 'Translation Timeout', | 311 |
124 8: 'Unexpected Script Error', | 312 /** |
125 9: 'Bad Origin', | 313 * Formats |date| as a Date object into a string. The format is like |
126 10: 'Script Load Error', | 314 * '2006-01-02 15:04:05'. |
127 }; | 315 * |
128 | 316 * @param {Date} date Date to be formatted. |
129 if (error < 0 || errorStrs.length <= error) { | 317 * @return {string} The formatted string. |
130 console.error('Invalid error code:', error); | 318 */ |
131 return 'Invalid Error Code'; | 319 function formatDate(date) { |
132 } | 320 var year = date.getFullYear(); |
133 return errorStrs[error]; | 321 var month = date.getMonth() + 1; |
134 } | 322 var day = date.getDate(); |
135 | 323 var hour = date.getHours(); |
136 /** | 324 var minute = date.getMinutes(); |
137 * Handles the message of 'prefsUpdated' from the browser. | 325 var second = date.getSeconds(); |
138 * | 326 |
139 * @param {Object} detail the object which represents pref values. | 327 var yearStr = padWithZeros(year, 4); |
140 */ | 328 var monthStr = padWithZeros(month, 2); |
141 function onPrefsUpdated(detail) { | 329 var dayStr = padWithZeros(day, 2); |
142 var ul; | 330 var hourStr = padWithZeros(hour, 2); |
143 | 331 var minuteStr = padWithZeros(minute, 2); |
144 ul = document.querySelector('#prefs-blocked-languages ul'); | 332 var secondStr = padWithZeros(second, 2); |
145 ul.innerHTML = ''; | 333 |
146 | 334 var str = yearStr + '-' + monthStr + '-' + dayStr + ' ' + hourStr + ':' + |
147 if ('translate_blocked_languages' in detail) { | 335 minuteStr + ':' + secondStr; |
148 var langs = detail['translate_blocked_languages']; | 336 |
149 | 337 return str; |
150 langs.forEach(function(langCode) { | 338 } |
151 var text = formatLanguageCode(langCode); | 339 |
152 | 340 /** |
153 var li = createLIWithDismissingButton(text, function() { | 341 * Appends a new TD element to the specified element. |
154 chrome.send('removePrefItem', | 342 * |
155 ['blocked_languages', langCode]); | 343 * @param {string} parent The element to which a new TD element is appended. |
156 }); | 344 * @param {string} content The text content of the element. |
157 ul.appendChild(li); | 345 * @param {string} className The class name of the element. |
158 }); | 346 */ |
159 } | 347 function appendTD(parent, content, className) { |
160 | 348 var td = document.createElement('td'); |
161 ul = document.querySelector('#prefs-language-blacklist ul'); | 349 td.textContent = content; |
162 ul.innerHTML = ''; | 350 td.className = className; |
163 | 351 parent.appendChild(td); |
164 if ('translate_language_blacklist' in detail) { | 352 } |
165 var langs = detail['translate_language_blacklist']; | 353 |
166 | 354 /** |
167 langs.forEach(function(langCode) { | 355 * Handles the message of 'languageDetectionInfoAdded' from the |
168 var text = formatLanguageCode(langCode); | 356 * browser. |
169 | 357 * |
170 var li = createLIWithDismissingButton(text, function() { | 358 * @param {Object} detail The object which represents the logs. |
171 chrome.send('removePrefItem', | 359 */ |
172 ['language_blacklist', langCode]); | 360 function onLanguageDetectionInfoAdded(detail) { |
173 }); | 361 detectionLogs.push(detail); |
174 ul.appendChild(li); | 362 |
175 }); | 363 var tr = document.createElement('tr'); |
176 } | 364 |
177 | 365 appendTD(tr, formatDate(new Date(detail['time'])), 'detection-logs-time'); |
178 ul = document.querySelector('#prefs-site-blacklist ul'); | 366 appendTD(tr, detail['url'], 'detection-logs-url'); |
179 ul.innerHTML = ''; | 367 appendTD( |
180 | 368 tr, formatLanguageCode(detail['content_language']), |
181 if ('translate_site_blacklist' in detail) { | 369 'detection-logs-content-language'); |
182 var sites = detail['translate_site_blacklist']; | 370 appendTD( |
183 | 371 tr, formatLanguageCode(detail['cld_language']), |
184 sites.forEach(function(site) { | 372 'detection-logs-cld-language'); |
185 var li = createLIWithDismissingButton(site, function() { | 373 appendTD(tr, detail['is_cld_reliable'], 'detection-logs-is-cld-reliable'); |
186 chrome.send('removePrefItem', ['site_blacklist', site]); | 374 appendTD(tr, detail['has_notranslate'], 'detection-logs-has-notranslate'); |
187 }); | 375 appendTD( |
188 ul.appendChild(li); | 376 tr, formatLanguageCode(detail['html_root_language']), |
189 }); | 377 'detection-logs-html-root-language'); |
190 } | 378 appendTD( |
191 | 379 tr, formatLanguageCode(detail['adopted_language']), |
192 ul = document.querySelector('#prefs-whitelists ul'); | 380 'detection-logs-adopted-language'); |
193 ul.innerHTML = ''; | 381 appendTD( |
194 | 382 tr, formatLanguageCode(detail['content']), 'detection-logs-content'); |
195 if ('translate_whitelists' in detail) { | 383 |
196 var pairs = detail['translate_whitelists']; | 384 // TD (and TR) can't use the CSS property 'max-height', so DIV |
197 | 385 // in the content is needed. |
198 Object.keys(pairs).forEach(function(fromLangCode) { | 386 var contentTD = tr.querySelector('.detection-logs-content'); |
199 var toLangCode = pairs[fromLangCode]; | 387 var div = document.createElement('div'); |
200 var text = formatLanguageCode(fromLangCode) + ' \u2192 ' + | 388 div.textContent = contentTD.textContent; |
201 formatLanguageCode(toLangCode); | 389 contentTD.textContent = ''; |
202 | 390 contentTD.appendChild(div); |
203 var li = createLIWithDismissingButton(text, function() { | 391 |
204 chrome.send('removePrefItem', | 392 var tabpanel = $('tabpanel-detection-logs'); |
205 ['whitelists', fromLangCode, toLangCode]); | 393 var tbody = tabpanel.getElementsByTagName('tbody')[0]; |
206 }); | 394 tbody.appendChild(tr); |
207 ul.appendChild(li); | 395 } |
208 }); | 396 |
209 } | 397 /** |
210 | 398 * Handles the message of 'translateErrorDetailsAdded' from the |
211 var p = $('prefs-too-often-denied'); | 399 * browser. |
212 p.classList.toggle('prefs-setting-disabled', | 400 * |
213 !detail['translate_too_often_denied']); | 401 * @param {Object} details The object which represents the logs. |
214 p.appendChild(createDismissingButton( | 402 */ |
215 chrome.send.bind(null, 'removePrefItem', ['too_often_denied']))); | 403 function onTranslateErrorDetailsAdded(details) { |
216 | 404 var tr = document.createElement('tr'); |
217 p = document.querySelector('#prefs-dump p'); | 405 |
218 var content = JSON.stringify(detail, null, 2); | 406 appendTD(tr, formatDate(new Date(details['time'])), 'error-logs-time'); |
219 p.textContent = content; | 407 appendTD(tr, details['url'], 'error-logs-url'); |
220 } | 408 appendTD( |
221 | 409 tr, |
222 /** | 410 details['error'] + ': ' + formatTranslateErrorsType(details['error']), |
223 * Handles the message of 'supportedLanguagesUpdated' from the browser. | 411 'error-logs-error'); |
224 * | 412 |
225 * @param {Object} details the object which represents the supported | 413 var tabpanel = $('tabpanel-error-logs'); |
226 * languages by the Translate server. | 414 var tbody = tabpanel.getElementsByTagName('tbody')[0]; |
227 */ | 415 tbody.appendChild(tr); |
228 function onSupportedLanguagesUpdated(details) { | 416 } |
229 var span = | 417 |
230 $('prefs-supported-languages-last-updated').querySelector('span'); | 418 /** |
231 span.textContent = formatDate(new Date(details['last_updated'])); | 419 * Handles the message of 'translateEventDetailsAdded' from the browser. |
232 | 420 * |
233 var ul = $('prefs-supported-languages-languages'); | 421 * @param {Object} details The object which contains event information. |
234 ul.innerHTML = ''; | 422 */ |
235 var languages = details['languages']; | 423 function onTranslateEventDetailsAdded(details) { |
236 for (var i = 0; i < languages.length; i++) { | 424 var tr = document.createElement('tr'); |
237 var language = languages[i]; | 425 appendTD(tr, formatDate(new Date(details['time'])), 'event-logs-time'); |
238 var li = document.createElement('li'); | 426 appendTD( |
239 | 427 tr, details['filename'] + ': ' + details['line'], 'event-logs-place'); |
240 var text = formatLanguageCode(language); | 428 appendTD(tr, details['message'], 'event-logs-message'); |
241 li.innerText = text; | 429 |
242 | 430 var tbody = $('tabpanel-event-logs').getElementsByTagName('tbody')[0]; |
243 ul.appendChild(li); | 431 tbody.appendChild(tr); |
244 } | 432 } |
245 } | 433 |
246 | 434 /** |
247 /** | 435 * The callback entry point from the browser. This function will be |
248 * Handles the message of 'countryUpdated' from the browser. | 436 * called by the browser. |
249 * | 437 * |
250 * @param {Object} details the object containing the country | 438 * @param {string} message The name of the sent message. |
251 * information. | 439 * @param {Object} details The argument of the sent message. |
252 */ | 440 */ |
253 function onCountryUpdated(details) { | 441 function messageHandler(message, details) { |
254 var p; | 442 switch (message) { |
255 p = $('country-override'); | 443 case 'languageDetectionInfoAdded': |
256 | 444 onLanguageDetectionInfoAdded(details); |
257 p.innerHTML = ''; | 445 break; |
258 | 446 case 'prefsUpdated': |
259 if ('country' in details) { | 447 onPrefsUpdated(details); |
260 var country = details['country']; | 448 break; |
261 | 449 case 'supportedLanguagesUpdated': |
262 var h2 = $('override-variations-country'); | 450 onSupportedLanguagesUpdated(details); |
263 h2.title = ( | 451 break; |
264 'Changing this value will override the permanent country stored ' + | 452 case 'countryUpdated': |
265 'by variations. Normally, this value gets automatically updated ' + | 453 onCountryUpdated(details); |
266 'with a new value received from the variations server when ' + | 454 break; |
267 'Chrome is updated.'); | 455 case 'translateErrorDetailsAdded': |
268 | 456 onTranslateErrorDetailsAdded(details); |
269 var input = document.createElement('input'); | 457 break; |
270 input.type = 'text'; | 458 case 'translateEventDetailsAdded': |
271 input.value = country; | 459 onTranslateEventDetailsAdded(details); |
272 | 460 break; |
273 var button = document.createElement('button'); | 461 default: |
274 button.textContent = 'update'; | 462 console.error('Unknown message:', message); |
275 button.addEventListener('click', function() { | 463 break; |
276 chrome.send('overrideCountry', [input.value]); | 464 } |
277 }, false); | 465 } |
278 p.appendChild(input); | 466 |
279 p.appendChild(document.createElement('br')); | 467 /** |
280 p.appendChild(button); | 468 * The callback of button#detetion-logs-dump. |
281 | 469 */ |
282 if ('update' in details && details['update']) { | 470 function onDetectionLogsDump() { |
283 var div1 = document.createElement('div'); | 471 var data = JSON.stringify(detectionLogs); |
284 div1.textContent = 'Permanent stored country updated.'; | 472 var blob = new Blob([data], {'type': 'text/json'}); |
285 var div2 = document.createElement('div'); | 473 var url = URL.createObjectURL(blob); |
286 div2.textContent = ('You will need to restart your browser ' + | 474 var filename = 'translate_internals_detect_logs_dump.json'; |
287 'for the changes to take effect.'); | 475 |
288 p.appendChild(div1); | 476 var a = document.createElement('a'); |
289 p.appendChild(div2); | 477 a.setAttribute('href', url); |
290 } | 478 a.setAttribute('download', filename); |
291 } else { | 479 |
292 p.textContent = 'Could not load country info from Variations.'; | 480 var event = document.createEvent('MouseEvent'); |
293 } | 481 event.initMouseEvent( |
294 } | 482 'click', true, true, window, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, null); |
295 | 483 a.dispatchEvent(event); |
296 /** | 484 } |
297 * Adds '0's to |number| as a string. |width| is length of the string | 485 |
298 * including '0's. | 486 return { |
299 * | 487 initialize: initialize, |
300 * @param {string} number The number to be converted into a string. | 488 messageHandler: messageHandler, |
301 * @param {number} width The width of the returned string. | 489 }; |
302 * @return {string} The formatted string. | 490 }); |
303 */ | 491 |
304 function padWithZeros(number, width) { | 492 /** |
305 var numberStr = number.toString(); | 493 * The entry point of the UI. |
306 var restWidth = width - numberStr.length; | 494 */ |
307 if (restWidth <= 0) | 495 function main() { |
308 return numberStr; | 496 cr.doc.addEventListener('DOMContentLoaded', cr.translateInternals.initialize); |
309 | 497 } |
310 return Array(restWidth + 1).join('0') + numberStr; | 498 |
311 } | 499 main(); |
312 | |
313 /** | |
314 * Formats |date| as a Date object into a string. The format is like | |
315 * '2006-01-02 15:04:05'. | |
316 * | |
317 * @param {Date} date Date to be formatted. | |
318 * @return {string} The formatted string. | |
319 */ | |
320 function formatDate(date) { | |
321 var year = date.getFullYear(); | |
322 var month = date.getMonth() + 1; | |
323 var day = date.getDate(); | |
324 var hour = date.getHours(); | |
325 var minute = date.getMinutes(); | |
326 var second = date.getSeconds(); | |
327 | |
328 var yearStr = padWithZeros(year, 4); | |
329 var monthStr = padWithZeros(month, 2); | |
330 var dayStr = padWithZeros(day, 2); | |
331 var hourStr = padWithZeros(hour, 2); | |
332 var minuteStr = padWithZeros(minute, 2); | |
333 var secondStr = padWithZeros(second, 2); | |
334 | |
335 var str = yearStr + '-' + monthStr + '-' + dayStr + ' ' + | |
336 hourStr + ':' + minuteStr + ':' + secondStr; | |
337 | |
338 return str; | |
339 } | |
340 | |
341 /** | |
342 * Appends a new TD element to the specified element. | |
343 * | |
344 * @param {string} parent The element to which a new TD element is appended. | |
345 * @param {string} content The text content of the element. | |
346 * @param {string} className The class name of the element. | |
347 */ | |
348 function appendTD(parent, content, className) { | |
349 var td = document.createElement('td'); | |
350 td.textContent = content; | |
351 td.className = className; | |
352 parent.appendChild(td); | |
353 } | |
354 | |
355 /** | |
356 * Handles the message of 'languageDetectionInfoAdded' from the | |
357 * browser. | |
358 * | |
359 * @param {Object} detail The object which represents the logs. | |
360 */ | |
361 function onLanguageDetectionInfoAdded(detail) { | |
362 detectionLogs.push(detail); | |
363 | |
364 var tr = document.createElement('tr'); | |
365 | |
366 appendTD(tr, formatDate(new Date(detail['time'])), 'detection-logs-time'); | |
367 appendTD(tr, detail['url'], 'detection-logs-url'); | |
368 appendTD(tr, formatLanguageCode(detail['content_language']), | |
369 'detection-logs-content-language'); | |
370 appendTD(tr, formatLanguageCode(detail['cld_language']), | |
371 'detection-logs-cld-language'); | |
372 appendTD(tr, detail['is_cld_reliable'], 'detection-logs-is-cld-reliable'); | |
373 appendTD(tr, detail['has_notranslate'], 'detection-logs-has-notranslate'); | |
374 appendTD(tr, formatLanguageCode(detail['html_root_language']), | |
375 'detection-logs-html-root-language'); | |
376 appendTD(tr, formatLanguageCode(detail['adopted_language']), | |
377 'detection-logs-adopted-language'); | |
378 appendTD(tr, formatLanguageCode(detail['content']), | |
379 'detection-logs-content'); | |
380 | |
381 // TD (and TR) can't use the CSS property 'max-height', so DIV | |
382 // in the content is needed. | |
383 var contentTD = tr.querySelector('.detection-logs-content'); | |
384 var div = document.createElement('div'); | |
385 div.textContent = contentTD.textContent; | |
386 contentTD.textContent = ''; | |
387 contentTD.appendChild(div); | |
388 | |
389 var tabpanel = $('tabpanel-detection-logs'); | |
390 var tbody = tabpanel.getElementsByTagName('tbody')[0]; | |
391 tbody.appendChild(tr); | |
392 } | |
393 | |
394 /** | |
395 * Handles the message of 'translateErrorDetailsAdded' from the | |
396 * browser. | |
397 * | |
398 * @param {Object} details The object which represents the logs. | |
399 */ | |
400 function onTranslateErrorDetailsAdded(details) { | |
401 var tr = document.createElement('tr'); | |
402 | |
403 appendTD(tr, formatDate(new Date(details['time'])), 'error-logs-time'); | |
404 appendTD(tr, details['url'], 'error-logs-url'); | |
405 appendTD( | |
406 tr, | |
407 details['error'] + ': ' + formatTranslateErrorsType(details['error']), | |
408 'error-logs-error'); | |
409 | |
410 var tabpanel = $('tabpanel-error-logs'); | |
411 var tbody = tabpanel.getElementsByTagName('tbody')[0]; | |
412 tbody.appendChild(tr); | |
413 } | |
414 | |
415 /** | |
416 * Handles the message of 'translateEventDetailsAdded' from the browser. | |
417 * | |
418 * @param {Object} details The object which contains event information. | |
419 */ | |
420 function onTranslateEventDetailsAdded(details) { | |
421 var tr = document.createElement('tr'); | |
422 appendTD(tr, formatDate(new Date(details['time'])), 'event-logs-time'); | |
423 appendTD(tr, details['filename'] + ': ' + details['line'], | |
424 'event-logs-place'); | |
425 appendTD(tr, details['message'], 'event-logs-message'); | |
426 | |
427 var tbody = $('tabpanel-event-logs').getElementsByTagName('tbody')[0]; | |
428 tbody.appendChild(tr); | |
429 } | |
430 | |
431 /** | |
432 * The callback entry point from the browser. This function will be | |
433 * called by the browser. | |
434 * | |
435 * @param {string} message The name of the sent message. | |
436 * @param {Object} details The argument of the sent message. | |
437 */ | |
438 function messageHandler(message, details) { | |
439 switch (message) { | |
440 case 'languageDetectionInfoAdded': | |
441 onLanguageDetectionInfoAdded(details); | |
442 break; | |
443 case 'prefsUpdated': | |
444 onPrefsUpdated(details); | |
445 break; | |
446 case 'supportedLanguagesUpdated': | |
447 onSupportedLanguagesUpdated(details); | |
448 break; | |
449 case 'countryUpdated': | |
450 onCountryUpdated(details); | |
451 break; | |
452 case 'translateErrorDetailsAdded': | |
453 onTranslateErrorDetailsAdded(details); | |
454 break; | |
455 case 'translateEventDetailsAdded': | |
456 onTranslateEventDetailsAdded(details); | |
457 break; | |
458 default: | |
459 console.error('Unknown message:', message); | |
460 break; | |
461 } | |
462 } | |
463 | |
464 /** | |
465 * The callback of button#detetion-logs-dump. | |
466 */ | |
467 function onDetectionLogsDump() { | |
468 var data = JSON.stringify(detectionLogs); | |
469 var blob = new Blob([data], {'type': 'text/json'}); | |
470 var url = URL.createObjectURL(blob); | |
471 var filename = 'translate_internals_detect_logs_dump.json'; | |
472 | |
473 var a = document.createElement('a'); | |
474 a.setAttribute('href', url); | |
475 a.setAttribute('download', filename); | |
476 | |
477 var event = document.createEvent('MouseEvent'); | |
478 event.initMouseEvent('click', true, true, window, 0, | |
479 0, 0, 0, 0, 0, 0, 0, 0, 0, null); | |
480 a.dispatchEvent(event); | |
481 } | |
482 | |
483 return { | |
484 initialize: initialize, | |
485 messageHandler: messageHandler, | |
486 }; | |
487 }); | |
488 | |
489 /** | |
490 * The entry point of the UI. | |
491 */ | |
492 function main() { | |
493 cr.doc.addEventListener('DOMContentLoaded', | |
494 cr.translateInternals.initialize); | |
495 } | |
496 | |
497 main(); | |
498 })(); | 500 })(); |
OLD | NEW |