Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / resources / feedback / js / feedback.js
blobf9800784d86250f310f4d36eac3abf0c5f687f48
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.
5 /** @type {string}
6 * @const
7 */
8 var FEEDBACK_LANDING_PAGE =
9 'https://www.google.com/support/chrome/go/feedback_confirmation';
10 /** @type {number}
11 * @const
13 var MAX_ATTACH_FILE_SIZE = 3 * 1024 * 1024;
15 /**
16 * @type {number}
17 * @const
19 var FEEDBACK_MIN_WIDTH = 500;
20 /**
21 * @type {number}
22 * @const
24 var FEEDBACK_MIN_HEIGHT = 625;
26 /** @type {number}
27 * @const
29 var CONTENT_MARGIN_HEIGHT = 40;
31 /** @type {number}
32 * @const
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};
45 /**
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];
52 if (!file) {
53 // User canceled file selection.
54 attachedFileBlob = null;
55 return;
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;
64 return;
67 attachedFileBlob = file.slice();
70 /**
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;
82 /**
83 * Creates and shows a window with the given url, if the window is not already
84 * open.
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) {
90 return function() {
91 if (window.id == 0) {
92 chrome.windows.create({url: url}, function(win) {
93 window.id = win.id;
94 chrome.app.window.current().show();
95 });
96 } else {
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},
108 function(win) {});
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');
121 description.focus();
122 return false;
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;
150 </if>
152 if (useSystemInfo) {
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);
158 } else {
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');
171 window.close();
174 return true;
178 * Click listener for the cancel button.
179 * @param {Event} e The click event being handled.
181 function cancel(e) {
182 e.preventDefault();
183 window.close();
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]);
194 var dataArray = [];
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;
212 } else {
213 $('attach-file').disabled = false;
214 $('screenshot-checkbox').disabled = false;
217 </if>
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.
238 * Flow:
239 * .) DOMContent Loaded -> . Request feedbackInfo object
240 * . Setup page event handlers
241 * .) Feedback Object Received -> . take screenshot
242 * . request email
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
266 // further delay.
267 window.webkitRequestAnimationFrame(function() {
268 resizeAppWindow();
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;
303 </if>
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);
337 </if>
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;
348 initialize();