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://www.google.com/support/chrome/go/feedback_confirmation';
13 var MAX_ATTACH_FILE_SIZE
= 3 * 1024 * 1024;
19 var FEEDBACK_MIN_WIDTH
= 500;
24 var FEEDBACK_MIN_HEIGHT
= 625;
29 var CONTENT_MARGIN_HEIGHT
= 40;
34 var MAX_SCREENSHOT_WIDTH
= 100;
36 var attachedFileBlob
= null;
37 var lastReader
= null;
39 var feedbackInfo
= null;
40 var systemInfo
= null;
42 var systemInfoWindow
= {id
: 0};
43 var histogramsWindow
= {id
: 0};
46 * Reads the selected file when the user selects a file.
47 * @param {Event} fileSelectedEvent The onChanged event for the file input box.
49 function onFileSelected(fileSelectedEvent
) {
50 $('attach-error').hidden
= true;
51 var file
= fileSelectedEvent
.target
.files
[0];
53 // User canceled file selection.
54 attachedFileBlob
= null;
58 if (file
.size
> MAX_ATTACH_FILE_SIZE
) {
59 $('attach-error').hidden
= false;
61 // Clear our selected file.
62 $('attach-file').value
= '';
63 attachedFileBlob
= null;
67 attachedFileBlob
= file
.slice();
71 * Clears the file that was attached to the report with the initial request.
72 * Instead we will now show the attach file button in case the user wants to
73 * attach another file.
75 function clearAttachedFile() {
76 $('custom-file-container').hidden
= true;
77 attachedFileBlob
= null;
78 feedbackInfo
.attachedFile
= null;
79 $('attach-file').hidden
= false;
83 * Creates and shows a window with the given url, if the window is not already
85 * @param {Object} window An object with the id of the window to update, or 0.
86 * @param {string} url The destination URL of the new window.
87 * @return {function()} A function to be called to open the window.
89 function windowOpener(window
, url
) {
92 chrome
.windows
.create({url
: url
}, function(win
) {
94 chrome
.app
.window
.current().show();
97 chrome
.windows
.update(window
.id
, {drawAttention
: true});
103 * Opens a new window with chrome://slow_trace, downloading performance data.
105 function openSlowTraceWindow() {
106 chrome
.windows
.create(
107 {url
: 'chrome://slow_trace/tracing.zip#' + feedbackInfo
.traceId
},
112 * Sends the report; after the report is sent, we need to be redirected to
113 * the landing page, but we shouldn't be able to navigate back, hence
114 * we open the landing page in a new tab and sendReport closes this tab.
115 * @return {boolean} True if the report was sent.
117 function sendReport() {
118 if ($('description-text').value
.length
== 0) {
119 var description
= $('description-text');
120 description
.placeholder
= loadTimeData
.getString('no-description');
125 // Prevent double clicking from sending additional reports.
126 $('send-report-button').disabled
= true;
127 console
.log('Feedback: Sending report');
128 if (!feedbackInfo
.attachedFile
&& attachedFileBlob
) {
129 feedbackInfo
.attachedFile
= { name
: $('attach-file').value
,
130 data
: attachedFileBlob
};
133 feedbackInfo
.description
= $('description-text').value
;
134 feedbackInfo
.pageUrl
= $('page-url-text').value
;
135 feedbackInfo
.email
= $('user-email-text').value
;
137 var useSystemInfo
= false;
138 var useHistograms
= false;
139 if ($('sys-info-checkbox') != null &&
140 $('sys-info-checkbox').checked
&&
141 systemInfo
!= null) {
142 // Send histograms along with system info.
143 useSystemInfo
= useHistograms
= true;
145 <if expr
="pp_ifdef('chromeos')">
146 if ($('performance-info-checkbox') == null ||
147 !($('performance-info-checkbox').checked
)) {
148 feedbackInfo
.traceId
= null;
153 if (feedbackInfo
.systemInformation
!= null) {
154 // Concatenate sysinfo if we had any initial system information
155 // sent with the feedback request event.
156 feedbackInfo
.systemInformation
=
157 feedbackInfo
.systemInformation
.concat(systemInfo
);
159 feedbackInfo
.systemInformation
= systemInfo
;
163 feedbackInfo
.sendHistograms
= useHistograms
;
165 // If the user doesn't want to send the screenshot.
166 if (!$('screenshot-checkbox').checked
)
167 feedbackInfo
.screenshot
= null;
169 chrome
.feedbackPrivate
.sendFeedback(feedbackInfo
, function(result
) {
170 window
.open(FEEDBACK_LANDING_PAGE
, '_blank');
178 * Click listener for the cancel button.
179 * @param {Event} e The click event being handled.
187 * Converts a blob data URL to a blob object.
188 * @param {string} url The data URL to convert.
189 * @return {Blob} Blob object containing the data.
191 function dataUrlToBlob(url
) {
192 var mimeString
= url
.split(',')[0].split(':')[1].split(';')[0];
193 var data
= atob(url
.split(',')[1]);
195 for (var i
= 0; i
< data
.length
; ++i
)
196 dataArray
.push(data
.charCodeAt(i
));
198 return new Blob([new Uint8Array(dataArray
)], {type
: mimeString
});
201 <if expr
="pp_ifdef('chromeos')">
203 * Update the page when performance feedback state is changed.
205 function performanceFeedbackChanged() {
206 if ($('performance-info-checkbox').checked
) {
207 $('attach-file').disabled
= true;
208 $('attach-file').checked
= false;
210 $('screenshot-checkbox').disabled
= true;
211 $('screenshot-checkbox').checked
= false;
213 $('attach-file').disabled
= false;
214 $('screenshot-checkbox').disabled
= false;
219 function resizeAppWindow() {
220 // We pick the width from the titlebar, which has no margins.
221 var width
= $('title-bar').scrollWidth
;
222 if (width
< FEEDBACK_MIN_WIDTH
)
223 width
= FEEDBACK_MIN_WIDTH
;
225 // We get the height by adding the titlebar height and the content height +
226 // margins. We can't get the margins for the content-pane here by using
227 // style.margin - the variable seems to not exist.
228 var height
= $('title-bar').scrollHeight
+
229 $('content-pane').scrollHeight
+ CONTENT_MARGIN_HEIGHT
;
230 if (height
< FEEDBACK_MIN_HEIGHT
)
231 height
= FEEDBACK_MIN_HEIGHT
;
233 chrome
.app
.window
.current().resizeTo(width
, height
);
237 * Initializes our page.
239 * .) DOMContent Loaded -> . Request feedbackInfo object
240 * . Setup page event handlers
241 * .) Feedback Object Received -> . take screenshot
243 * . request System info
244 * . request i18n strings
245 * .) Screenshot taken -> . Show Feedback window.
247 function initialize() {
248 // TODO(rkc): Remove logging once crbug.com/284662 is closed.
249 console
.log('FEEDBACK_DEBUG: feedback.js: initialize()');
251 // Add listener to receive the feedback info object.
252 chrome
.runtime
.onMessage
.addListener(function(request
, sender
, sendResponse
) {
253 if (request
.sentFromEventPage
) {
254 // TODO(rkc): Remove logging once crbug.com/284662 is closed.
255 console
.log('FEEDBACK_DEBUG: Received feedbackInfo.');
256 feedbackInfo
= request
.data
;
257 $('description-text').textContent
= feedbackInfo
.description
;
258 if (feedbackInfo
.pageUrl
)
259 $('page-url-text').value
= feedbackInfo
.pageUrl
;
261 takeScreenshot(function(screenshotCanvas
) {
262 // TODO(rkc): Remove logging once crbug.com/284662 is closed.
263 console
.log('FEEDBACK_DEBUG: Taken screenshot. Showing window.');
265 // We've taken our screenshot, show the feedback page without any
267 window
.webkitRequestAnimationFrame(function() {
270 chrome
.app
.window
.current().show();
272 var screenshotDataUrl
= screenshotCanvas
.toDataURL('image/png');
273 $('screenshot-image').src
= screenshotDataUrl
;
274 $('screenshot-image').classList
.toggle('wide-screen',
275 $('screenshot-image').width
> MAX_SCREENSHOT_WIDTH
);
276 feedbackInfo
.screenshot
= dataUrlToBlob(screenshotDataUrl
);
279 chrome
.feedbackPrivate
.getUserEmail(function(email
) {
280 $('user-email-text').value
= email
;
283 chrome
.feedbackPrivate
.getSystemInformation(function(sysInfo
) {
284 systemInfo
= sysInfo
;
287 // An extension called us with an attached file.
288 if (feedbackInfo
.attachedFile
) {
289 $('attached-filename-text').textContent
=
290 feedbackInfo
.attachedFile
.name
;
291 attachedFileBlob
= feedbackInfo
.attachedFile
.data
;
292 $('custom-file-container').hidden
= false;
293 $('attach-file').hidden
= true;
296 <if expr
="pp_ifdef('chromeos')">
297 if (feedbackInfo
.traceId
&& ($('performance-info-area'))) {
298 $('performance-info-area').hidden
= false;
299 $('performance-info-checkbox').checked
= true;
300 performanceFeedbackChanged();
301 $('performance-info-link').onclick
= openSlowTraceWindow
;
305 chrome
.feedbackPrivate
.getStrings(function(strings
) {
306 loadTimeData
.data
= strings
;
307 i18nTemplate
.process(document
, loadTimeData
);
309 if ($('sys-info-url')) {
310 // Opens a new window showing the current system info.
311 $('sys-info-url').onclick
=
312 windowOpener(systemInfoWindow
, 'chrome://system');
314 if ($('histograms-url')) {
315 // Opens a new window showing the histogram metrics.
316 $('histograms-url').onclick
=
317 windowOpener(histogramsWindow
, 'chrome://histograms');
323 window
.addEventListener('DOMContentLoaded', function() {
324 // TODO(rkc): Remove logging once crbug.com/284662 is closed.
325 console
.log('FEEDBACK_DEBUG: feedback.js: DOMContentLoaded');
326 // Ready to receive the feedback object.
327 chrome
.runtime
.sendMessage({ready
: true});
329 // Setup our event handlers.
330 $('attach-file').addEventListener('change', onFileSelected
);
331 $('send-report-button').onclick
= sendReport
;
332 $('cancel-button').onclick
= cancel
;
333 $('remove-attached-file').onclick
= clearAttachedFile
;
334 <if expr
="pp_ifdef('chromeos')">
335 $('performance-info-checkbox').addEventListener(
336 'change', performanceFeedbackChanged
);
339 chrome
.windows
.onRemoved
.addListener(function(windowId
, removeInfo
) {
340 if (windowId
== systemInfoWindow
.id
)
341 systemInfoWindow
.id
= 0;
342 else if (windowId
== histogramsWindow
.id
)
343 histogramsWindow
.id
= 0;