1 // Copyright 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 * @type {string} The host id corresponding to the user's VM. The @pending
9 * place-holder instructs the Orchestrator to abandon any pending host,
10 * and is used if no host id is provided by the main window.
12 var hostId
= '@pending';
15 * @type {string} The network stats at the time the feedback consent dialog
18 var connectionStats
= null;
21 * @type {string} "no" => user did not request a VM reset; "yes" => VM was
22 * successfully reset; "failed" => user requested a reset, but it failed.
24 var abandonHost
= 'no';
27 * @type {Window} The main application window.
29 var applicationWindow
= null;
32 * @type {string} An unique identifier that links the feedback post with the
33 * logs uploaded by the host.
35 var crashServiceReportId
= '';
38 * @param {string} email
39 * @param {string} realName
41 function onUserInfo(email
, realName
) {
42 /** @type {number} Identifies this product to Google Feedback. **/
43 var productId
= 93407;
45 /** @type {string} The base URL for Google Feedback. */
46 var url
= 'https://www.google.com/tools/feedback/survey/xhtml';
48 /** @type {string} The feedback 'bucket', used for clustering. */
49 var bucket
= 'feedback';
51 /** @type {string} The user's locale, used to localize the feedback page. */
52 var locale
= chrome
.i18n
.getMessage('@@ui_locale');
55 '?productId=' + productId
+
56 '&bucket=' + escape(bucket
) +
57 '&hl=' + escape(locale
) +
58 '&psd_email=' + escape(email
) +
59 '&psd_hostId=' + escape(hostId
) +
60 '&psd_abandonHost=' + escape(abandonHost
) +
61 '&psd_crashServiceReportId=' + escape(crashServiceReportId
) +
62 '&psd_connectionStats=' + escape(connectionStats
));
65 // If the VM was successfully abandoned, close the application.
66 if (abandonHost
== 'yes') {
67 applicationWindow
.close();
72 * @param {boolean} waiting
74 function setWaiting(waiting
) {
75 var ok
= document
.getElementById('feedback-consent-ok');
76 var cancel
= document
.getElementById('feedback-consent-cancel');
77 var abandon
= document
.getElementById('abandon-host');
78 var working
= document
.getElementById('working');
79 ok
.disabled
= waiting
;
80 cancel
.disabled
= waiting
;
81 abandon
.disabled
= waiting
;
82 working
.hidden
= !waiting
;
85 function showError() {
87 var error
= document
.getElementById('abandon-failed');
88 var abandon
= document
.getElementById('abandon-host');
89 var logs
= document
.getElementById('include-logs');
90 var formBody
= document
.getElementById('form-body');
92 abandon
.checked
= false;
94 abandonHost
= 'failed';
95 crashServiceReportId
= '';
96 formBody
.hidden
= true;
101 * @return {string} A random string ID.
103 function generateId() {
104 var idArray
= new Uint8Array(20);
105 crypto
.getRandomValues(idArray
);
106 return btoa(String
.fromCharCode
.apply(null, idArray
));
110 * @param {string} token
112 function onToken(token
) {
113 var getUserInfo = function() {
114 var oauth2Api
= new remoting
.OAuth2ApiImpl();
115 oauth2Api
.getUserInfo(
116 onUserInfo
, onUserInfo
.bind(null, 'unknown', 'unknown'), token
);
119 onUserInfo('unknown', 'unknown');
121 if (abandonHost
== 'yes') {
123 'abandonHost': 'true',
124 'crashServiceReportId': crashServiceReportId
127 'Authorization': 'OAuth ' + token
,
128 'Content-type': 'application/json'
130 var uri
= remoting
.settings
.APP_REMOTING_API_BASE_URL
+
131 '/applications/' + remoting
.settings
.getAppRemotingApplicationId() +
134 /** @param {XMLHttpRequest} xhr */
135 var onDone = function(xhr
) {
136 if (xhr
.status
>= 200 && xhr
.status
< 300) {
142 remoting
.xhr
.post(uri
, onDone
, JSON
.stringify(body
), headers
);
151 var abandon
= /** @type {HTMLInputElement} */
152 (document
.getElementById('abandon-host'));
153 if (abandon
.checked
) {
156 chrome
.identity
.getAuthToken({ 'interactive': false }, onToken
);
159 function onCancel() {
163 function onToggleAbandon() {
164 var abandon
= document
.getElementById('abandon-host');
165 var includeLogs
= document
.getElementById('include-logs');
166 var includeLogsLabel
= document
.getElementById('include-logs-label');
167 var learnMoreLink
= document
.getElementById('learn-more');
168 includeLogs
.disabled
= !abandon
.checked
;
169 if (abandon
.checked
) {
170 includeLogsLabel
.classList
.remove('disabled');
171 learnMoreLink
.classList
.remove('disabled');
173 includeLogsLabel
.classList
.add('disabled');
174 learnMoreLink
.classList
.add('disabled');
178 function onToggleLogs() {
179 var includeLogs
= document
.getElementById('include-logs');
180 if (includeLogs
.checked
) {
181 crashServiceReportId
= generateId();
183 crashServiceReportId
= '';
187 function onLearnMore(event
) {
188 event
.preventDefault(); // Clicking the link should not tick the checkbox.
189 var learnMoreLink
= document
.getElementById('learn-more');
190 var learnMoreInfobox
= document
.getElementById('privacy-info');
191 learnMoreLink
.hidden
= true;
192 learnMoreInfobox
.hidden
= false;
196 function resizeWindow() {
197 var borderY
= window
.outerHeight
- window
.innerHeight
;
198 window
.resizeTo(window
.outerWidth
, document
.body
.clientHeight
+ borderY
);
202 window
.addEventListener('message', onWindowMessage
, false);
203 remoting
.settings
= new remoting
.Settings();
205 var ok
= document
.getElementById('feedback-consent-ok');
206 var cancel
= document
.getElementById('feedback-consent-cancel');
207 var abandon
= document
.getElementById('abandon-host-label');
208 var includeLogs
= document
.getElementById('include-logs-label');
209 var learnMoreLink
= document
.getElementById('learn-more');
210 ok
.addEventListener('click', onOk
, false);
211 cancel
.addEventListener('click', onCancel
, false);
212 abandon
.addEventListener('click', onToggleAbandon
, false);
213 includeLogs
.addEventListener('click', onToggleLogs
, false);
214 learnMoreLink
.addEventListener('click', onLearnMore
, false);
218 /** @param {Event} event */
219 function onWindowMessage(event
) {
220 applicationWindow
= event
.source
;
221 var method
= /** @type {string} */ (event
.data
['method']);
222 if (method
== 'init') {
223 if (event
.data
['hostId']) {
224 hostId
= /** @type {string} */ (event
.data
['hostId']);
226 connectionStats
= /** @type {string} */ (event
.data
['connectionStats']);
230 window
.addEventListener('load', onLoad
, false);