1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
|
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/** @type {string}
* @const
*/
var FEEDBACK_LANDING_PAGE =
'https://www.google.com/support/chrome/go/feedback_confirmation';
/** @type {number}
* @const
*/
var MAX_ATTACH_FILE_SIZE = 3 * 1024 * 1024;
var attachedFileBlob = null;
var lastReader = null;
var feedbackInfo = null;
var systemInfo = null;
var systemInfoWindowId = 0;
/**
* Reads the selected file when the user selects a file.
* @param {Event} fileSelectedEvent The onChanged event for the file input box.
*/
function onFileSelected(fileSelectedEvent) {
$('attach-error').hidden = true;
var file = fileSelectedEvent.target.files[0];
if (!file) {
// User canceled file selection.
attachedFileBlob = null;
return;
}
if (file.size > MAX_ATTACH_FILE_SIZE) {
$('attach-error').hidden = false;
// Clear our selected file.
$('attach-file').value = '';
attachedFileBlob = null;
return;
}
attachedFileBlob = file.slice();
}
/**
* Clears the file that was attached to the report with the initial request.
* Instead we will now show the attach file button in case the user wants to
* attach another file.
*/
function clearAttachedFile() {
$('custom-file-container').hidden = true;
attachedFileBlob = null;
feedbackInfo.attachedFile = null;
$('attach-file').hidden = false;
}
/**
* Opens a new window with chrome://system, showing the current system info.
*/
function openSystemInfoWindow() {
if (systemInfoWindowId == 0) {
chrome.windows.create({url: 'chrome://system'}, function(win) {
systemInfoWindowId = win.id;
chrome.app.window.current().show();
});
} else {
chrome.windows.update(systemInfoWindowId, {drawAttention: true});
}
}
/**
* Sends the report; after the report is sent, we need to be redirected to
* the landing page, but we shouldn't be able to navigate back, hence
* we open the landing page in a new tab and sendReport closes this tab.
* @return {boolean} True if the report was sent.
*/
function sendReport() {
if ($('description-text').value.length == 0) {
var description = $('description-text');
description.placeholder = loadTimeData.getString('no-description');
description.focus();
return false;
}
console.log('Feedback: Sending report');
if (!feedbackInfo.attachedFile && attachedFileBlob) {
feedbackInfo.attachedFile = { name: $('attach-file').value,
data: attachedFileBlob };
}
feedbackInfo.description = $('description-text').value;
feedbackInfo.pageUrl = $('page-url-text').value;
feedbackInfo.email = $('user-email-text').value;
var useSystemInfo = false;
// On ChromeOS, since we gather System info, check if the user has given his
// permission for us to send system info.
<if expr="pp_ifdef('chromeos')">
if ($('sys-info-checkbox') != null &&
$('sys-info-checkbox').checked &&
systemInfo != null) {
useSystemInfo = true;
}
</if>
// On NonChromeOS, we don't have any system information gathered except the
// Chrome version and the OS version. Hence for Chrome, pass the system info
// through.
<if expr="not pp_ifdef('chromeos')">
if (systemInfo != null)
useSystemInfo = true;
</if>
if (useSystemInfo) {
if (feedbackInfo.systemInformation != null) {
// Concatenate sysinfo if we had any initial system information
// sent with the feedback request event.
feedbackInfo.systemInformation =
feedbackInfo.systemInformation.concat(systemInfo);
} else {
feedbackInfo.systemInformation = systemInfo;
}
}
// If the user doesn't want to send the screenshot.
if (!$('screenshot-checkbox').checked)
feedbackInfo.screenshot = null;
chrome.feedbackPrivate.sendFeedback(feedbackInfo, function(result) {
window.open(FEEDBACK_LANDING_PAGE, '_blank');
window.close();
});
return true;
}
/**
* Click listener for the cancel button.
* @param {Event} e The click event being handled.
*/
function cancel(e) {
e.preventDefault();
window.close();
}
/**
* Converts a blob data URL to a blob object.
* @param {string} url The data URL to convert.
* @return {Blob} Blob object containing the data.
*/
function dataUrlToBlob(url) {
var mimeString = url.split(',')[0].split(':')[1].split(';')[0];
var data = atob(url.split(',')[1]);
var dataArray = [];
for (var i = 0; i < data.length; ++i)
dataArray.push(data.charCodeAt(i));
return new Blob([new Uint8Array(dataArray)], {type: mimeString});
}
/**
* Initializes our page.
* Flow:
* .) DOMContent Loaded -> . Request feedbackInfo object
* . Setup page event handlers
* .) Feedback Object Received -> . take screenshot
* . request email
* . request System info
* . request i18n strings
* .) Screenshot taken -> . Show Feedback window.
*/
function initialize() {
// Add listener to receive the feedback info object.
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.sentFromEventPage) {
feedbackInfo = request.data;
$('description-text').textContent = feedbackInfo.description;
if (feedbackInfo.pageUrl)
$('page-url-text').value = feedbackInfo.pageUrl;
takeScreenshot(function(screenshotDataUrl) {
$('screenshot-image').src = screenshotDataUrl;
feedbackInfo.screenshot = dataUrlToBlob(screenshotDataUrl);
chrome.app.window.current().show();
});
chrome.feedbackPrivate.getUserEmail(function(email) {
$('user-email-text').value = email;
});
chrome.feedbackPrivate.getSystemInformation(function(sysInfo) {
systemInfo = sysInfo;
});
// An extension called us with an attached file.
if (feedbackInfo.attachedFile) {
$('attached-filename-text').textContent =
feedbackInfo.attachedFile.name;
attachedFileBlob = feedbackInfo.attachedFile.data;
$('custom-file-container').hidden = false;
$('attach-file').hidden = true;
}
chrome.feedbackPrivate.getStrings(function(strings) {
loadTimeData.data = strings;
i18nTemplate.process(document, loadTimeData);
});
}
});
window.addEventListener('DOMContentLoaded', function() {
// Ready to receive the feedback object.
chrome.runtime.sendMessage({ready: true});
// Setup our event handlers.
$('attach-file').addEventListener('change', onFileSelected);
$('send-report-button').onclick = sendReport;
$('cancel-button').onclick = cancel;
$('remove-attached-file').onclick = clearAttachedFile;
chrome.windows.onRemoved.addListener(function(windowId, removeInfo) {
if (windowId == systemInfoWindowId)
systemInfoWindowId = 0;
});
if ($('sysinfo-url')) {
$('sysinfo-url').onclick = openSystemInfoWindow;
}
});
}
initialize();
|