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
3 // found in the LICENSE file.
8 var FEEDBACK_LANDING_PAGE
=
9 'https://support.google.com/chrome/go/feedback_confirmation';
13 var MAX_ATTACH_FILE_SIZE
= 3 * 1024 * 1024;
19 var FEEDBACK_MIN_WIDTH
= 500;
24 var FEEDBACK_MIN_HEIGHT
= 585;
29 var CONTENT_MARGIN_HEIGHT
= 40;
34 var MAX_SCREENSHOT_WIDTH
= 100;
39 var SYSINFO_WINDOW_ID
= 'sysinfo_window';
44 var STATS_WINDOW_ID
= 'stats_window';
46 var attachedFileBlob
= null;
47 var lastReader
= null;
49 var feedbackInfo
= null;
50 var systemInfo
= null;
53 * Reads the selected file when the user selects a file.
54 * @param {Event} fileSelectedEvent The onChanged event for the file input box.
56 function onFileSelected(fileSelectedEvent
) {
57 $('attach-error').hidden
= true;
58 var file
= fileSelectedEvent
.target
.files
[0];
60 // User canceled file selection.
61 attachedFileBlob
= null;
65 if (file
.size
> MAX_ATTACH_FILE_SIZE
) {
66 $('attach-error').hidden
= false;
68 // Clear our selected file.
69 $('attach-file').value
= '';
70 attachedFileBlob
= null;
74 attachedFileBlob
= file
.slice();
78 * Clears the file that was attached to the report with the initial request.
79 * Instead we will now show the attach file button in case the user wants to
80 * attach another file.
82 function clearAttachedFile() {
83 $('custom-file-container').hidden
= true;
84 attachedFileBlob
= null;
85 feedbackInfo
.attachedFile
= null;
86 $('attach-file').hidden
= false;
90 * Creates a closure that creates or shows a window with the given url.
91 * @param {string} windowId A string with the ID of the window we are opening.
92 * @param {string} url The destination URL of the new window.
93 * @return {function()} A function to be called to open the window.
95 function windowOpener(windowId
, url
) {
98 chrome
.app
.window
.create(url
, {id
: windowId
});
103 * Opens a new window with chrome://slow_trace, downloading performance data.
105 function openSlowTraceWindow() {
106 chrome
.app
.window
.create(
107 'chrome://slow_trace/tracing.zip#' + feedbackInfo
.traceId
);
111 * Sends the report; after the report is sent, we need to be redirected to
112 * the landing page, but we shouldn't be able to navigate back, hence
113 * we open the landing page in a new tab and sendReport closes this tab.
114 * @return {boolean} True if the report was sent.
116 function sendReport() {
117 if ($('description-text').value
.length
== 0) {
118 var description
= $('description-text');
119 description
.placeholder
= loadTimeData
.getString('no-description');
124 // Prevent double clicking from sending additional reports.
125 $('send-report-button').disabled
= true;
126 console
.log('Feedback: Sending report');
127 if (!feedbackInfo
.attachedFile
&& attachedFileBlob
) {
128 feedbackInfo
.attachedFile
= { name
: $('attach-file').value
,
129 data
: attachedFileBlob
};
132 feedbackInfo
.description
= $('description-text').value
;
133 feedbackInfo
.pageUrl
= $('page-url-text').value
;
134 feedbackInfo
.email
= $('user-email-text').value
;
136 var useSystemInfo
= false;
137 var useHistograms
= false;
138 if ($('sys-info-checkbox') != null &&
139 $('sys-info-checkbox').checked
&&
140 systemInfo
!= null) {
141 // Send histograms along with system info.
142 useSystemInfo
= useHistograms
= true;
145 if ($('performance-info-checkbox') == null ||
146 !($('performance-info-checkbox').checked
)) {
147 feedbackInfo
.traceId
= null;
152 if (feedbackInfo
.systemInformation
!= null) {
153 // Concatenate sysinfo if we had any initial system information
154 // sent with the feedback request event.
155 feedbackInfo
.systemInformation
=
156 feedbackInfo
.systemInformation
.concat(systemInfo
);
158 feedbackInfo
.systemInformation
= systemInfo
;
162 feedbackInfo
.sendHistograms
= useHistograms
;
164 // If the user doesn't want to send the screenshot.
165 if (!$('screenshot-checkbox').checked
)
166 feedbackInfo
.screenshot
= null;
168 chrome
.feedbackPrivate
.sendFeedback(feedbackInfo
, function(result
) {
169 window
.open(FEEDBACK_LANDING_PAGE
, '_blank');
177 * Click listener for the cancel button.
178 * @param {Event} e The click event being handled.
186 * Converts a blob data URL to a blob object.
187 * @param {string} url The data URL to convert.
188 * @return {Blob} Blob object containing the data.
190 function dataUrlToBlob(url
) {
191 var mimeString
= url
.split(',')[0].split(':')[1].split(';')[0];
192 var data
= atob(url
.split(',')[1]);
194 for (var i
= 0; i
< data
.length
; ++i
)
195 dataArray
.push(data
.charCodeAt(i
));
197 return new Blob([new Uint8Array(dataArray
)], {type
: mimeString
});
202 * Update the page when performance feedback state is changed.
204 function performanceFeedbackChanged() {
205 if ($('performance-info-checkbox').checked
) {
206 $('attach-file').disabled
= true;
207 $('attach-file').checked
= false;
209 $('screenshot-checkbox').disabled
= true;
210 $('screenshot-checkbox').checked
= false;
212 $('attach-file').disabled
= false;
213 $('screenshot-checkbox').disabled
= false;
218 function resizeAppWindow() {
219 // We pick the width from the titlebar, which has no margins.
220 var width
= $('title-bar').scrollWidth
;
221 if (width
< FEEDBACK_MIN_WIDTH
)
222 width
= FEEDBACK_MIN_WIDTH
;
224 // We get the height by adding the titlebar height and the content height +
225 // margins. We can't get the margins for the content-pane here by using
226 // style.margin - the variable seems to not exist.
227 var height
= $('title-bar').scrollHeight
+
228 $('content-pane').scrollHeight
+ CONTENT_MARGIN_HEIGHT
;
229 if (height
< FEEDBACK_MIN_HEIGHT
)
230 height
= FEEDBACK_MIN_HEIGHT
;
232 chrome
.app
.window
.current().resizeTo(width
, height
);
236 * Initializes our page.
238 * .) DOMContent Loaded -> . Request feedbackInfo object
239 * . Setup page event handlers
240 * .) Feedback Object Received -> . take screenshot
242 * . request System info
243 * . request i18n strings
244 * .) Screenshot taken -> . Show Feedback window.
246 function initialize() {
247 // Add listener to receive the feedback info object.
248 chrome
.runtime
.onMessage
.addListener(function(request
, sender
, sendResponse
) {
249 if (request
.sentFromEventPage
) {
250 feedbackInfo
= request
.data
;
251 $('description-text').textContent
= feedbackInfo
.description
;
252 if (feedbackInfo
.pageUrl
)
253 $('page-url-text').value
= feedbackInfo
.pageUrl
;
255 takeScreenshot(function(screenshotCanvas
) {
256 // We've taken our screenshot, show the feedback page without any
258 window
.webkitRequestAnimationFrame(function() {
261 chrome
.app
.window
.current().show();
263 var screenshotDataUrl
= screenshotCanvas
.toDataURL('image/png');
264 $('screenshot-image').src
= screenshotDataUrl
;
265 $('screenshot-image').classList
.toggle('wide-screen',
266 $('screenshot-image').width
> MAX_SCREENSHOT_WIDTH
);
267 feedbackInfo
.screenshot
= dataUrlToBlob(screenshotDataUrl
);
270 chrome
.feedbackPrivate
.getUserEmail(function(email
) {
271 $('user-email-text').value
= email
;
274 chrome
.feedbackPrivate
.getSystemInformation(function(sysInfo
) {
275 systemInfo
= sysInfo
;
278 // An extension called us with an attached file.
279 if (feedbackInfo
.attachedFile
) {
280 $('attached-filename-text').textContent
=
281 feedbackInfo
.attachedFile
.name
;
282 attachedFileBlob
= feedbackInfo
.attachedFile
.data
;
283 $('custom-file-container').hidden
= false;
284 $('attach-file').hidden
= true;
288 if (feedbackInfo
.traceId
&& ($('performance-info-area'))) {
289 $('performance-info-area').hidden
= false;
290 $('performance-info-checkbox').checked
= true;
291 performanceFeedbackChanged();
292 $('performance-info-link').onclick
= openSlowTraceWindow
;
296 chrome
.feedbackPrivate
.getStrings(function(strings
) {
297 loadTimeData
.data
= strings
;
298 i18nTemplate
.process(document
, loadTimeData
);
300 if ($('sys-info-url')) {
301 // Opens a new window showing the current system info.
302 $('sys-info-url').onclick
=
303 windowOpener(SYSINFO_WINDOW_ID
, 'chrome://system');
305 if ($('histograms-url')) {
306 // Opens a new window showing the histogram metrics.
307 $('histograms-url').onclick
=
308 windowOpener(STATS_WINDOW_ID
, 'chrome://histograms');
310 // Make sure our focus starts on the description field.
311 $('description-text').focus();
316 window
.addEventListener('DOMContentLoaded', function() {
317 // Ready to receive the feedback object.
318 chrome
.runtime
.sendMessage({ready
: true});
320 // Setup our event handlers.
321 $('attach-file').addEventListener('change', onFileSelected
);
322 $('send-report-button').onclick
= sendReport
;
323 $('cancel-button').onclick
= cancel
;
324 $('remove-attached-file').onclick
= clearAttachedFile
;
326 $('performance-info-checkbox').addEventListener(
327 'change', performanceFeedbackChanged
);