1 | /* global API */ |
||
2 | var $j = jQuery.noConflict(); |
||
3 | |||
4 | $j(document).ready(function () { |
||
5 | |||
6 | $j(document).click(function (event) { |
||
7 | var passwordPickerRef = '.passwordPickerIframe'; |
||
8 | if (!$j(event.target).closest(passwordPickerRef).length) { |
||
9 | if ($j(passwordPickerRef).is(":visible")) { |
||
10 | removePasswordPicker(); |
||
11 | } |
||
12 | } |
||
13 | }); |
||
14 | |||
15 | var _this = this; |
||
16 | Array.prototype.findUrl = function (match) { |
||
0 ignored issues
–
show
Compatibility
Best Practice
introduced
by
Loading history...
|
|||
17 | return this.filter(function (item) { |
||
18 | return typeof item === 'string' && item.indexOf(match) > -1; |
||
19 | }); |
||
20 | }; |
||
21 | |||
22 | function removePasswordPicker() { |
||
23 | activeForm = undefined; |
||
24 | $j('.passwordPickerIframe').remove(); |
||
25 | } |
||
26 | |||
27 | _this.removePasswordPicker = removePasswordPicker; |
||
28 | |||
29 | function enterLoginDetails(login, allowSubmit) { |
||
30 | var username; |
||
31 | |||
32 | if (login.hasOwnProperty('username')) { |
||
33 | username = (login.username !== '' ) ? login.username : login.email; |
||
34 | } |
||
35 | if (!username) { |
||
36 | username = null; |
||
37 | } |
||
38 | |||
39 | fillPassword(username, login.password); |
||
40 | |||
41 | if (activeForm) { |
||
42 | API.runtime.sendMessage(API.runtime.id, {method: 'isAutoSubmitEnabled'}).then(function (isEnabled) { |
||
43 | if (isEnabled && allowSubmit) { |
||
44 | submitLoginForm(username); |
||
45 | } |
||
46 | }); |
||
47 | } |
||
48 | } |
||
49 | |||
50 | _this.enterLoginDetails = enterLoginDetails; |
||
51 | |||
52 | function submitLoginForm(username) { |
||
53 | if (!activeForm) { |
||
54 | // @TODO detect login form on the current page |
||
55 | return; |
||
56 | } |
||
57 | |||
58 | var formEl = $j(activeForm).closest('form'); |
||
59 | var iframeUrl = API.extension.getURL('/html/inject/auto_login.html'); |
||
60 | $j('#loginPopupIframe').remove(); |
||
61 | var loginPopup = $j('<iframe class="loginPopupIframe" scrolling="no" frameborder="0" src="' + iframeUrl + '"></iframe>'); |
||
62 | var padding = parseInt($j(formEl).css('padding').replace('px', '')); |
||
63 | var margin = parseInt($j(formEl).css('margin').replace('px', '')); |
||
64 | var height = Math.round($j(formEl).height() + (padding * 2) + (margin * 2)); |
||
65 | var width = Math.round($j(formEl).width() + (padding * 2) + (margin * 2)); |
||
66 | loginPopup.attr('height', height); |
||
67 | loginPopup.attr('width', width); |
||
68 | loginPopup.css('position', 'absolute'); |
||
69 | loginPopup.css('z-index', getMaxZ() + 1); |
||
70 | loginPopup.css('background-color', 'rgba(0, 0, 0, 0.73)'); |
||
71 | loginPopup.css('left', Math.floor($j(formEl).offset().left - padding - margin)); |
||
72 | loginPopup.css('top', Math.floor($j(formEl).offset().top - padding - margin)); |
||
73 | removePasswordPicker(); |
||
74 | $j(document.body).prepend(loginPopup); |
||
75 | API.runtime.sendMessage(API.runtime.id, {'setIframeUsername': username}).then(function () { |
||
76 | $j(formEl).submit(); |
||
77 | setTimeout(function () { |
||
78 | loginPopup.remove(); |
||
79 | }, 2000); |
||
80 | }); |
||
81 | } |
||
82 | |||
83 | function getMaxZ() { |
||
84 | return Math.max.apply(null, |
||
85 | $j.map($j('body *'), function (e) { |
||
86 | if ($j(e).css('position') !== 'static') |
||
0 ignored issues
–
show
There is no return statement if
$j(e).css("position") !== "static" is false . Are you sure this is correct? If so, consider adding return; explicitly.
This check looks for functions where a Consider this little piece of code function isBig(a) {
if (a > 5000) {
return "yes";
}
}
console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined
The function This behaviour may not be what you had intended. In any case, you can add a
Loading history...
|
|||
87 | return parseInt($j(e).css('z-index')) || 1; |
||
0 ignored issues
–
show
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.
Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later. Consider: if (a > 0)
b = 42;
If you or someone else later decides to put another statement in, only the first statement will be executed. if (a > 0)
console.log("a > 0");
b = 42;
In this case the statement if (a > 0) {
console.log("a > 0");
b = 42;
}
ensures that the proper code will be executed conditionally no matter how many statements are added or removed.
Loading history...
|
|||
88 | })); |
||
89 | } |
||
90 | |||
91 | var activeForm; |
||
92 | |||
93 | function showPasswordPicker(form) { |
||
94 | var jPasswordPicker = $j('.passwordPickerIframe'); |
||
95 | if (jPasswordPicker.length > 1) { |
||
96 | return; |
||
97 | } |
||
98 | var loginField = $j(form[0]); |
||
99 | var loginFieldPos = loginField.offset(); |
||
100 | var loginFieldVisible = loginField.is(':visible'); |
||
101 | |||
102 | var position = $j(form[1]).position(); |
||
0 ignored issues
–
show
|
|||
103 | var passwordField = $j(form[1]); |
||
104 | var passwordFieldPos = passwordField.offset(); |
||
105 | var passwordFieldVisible = loginField.is(':visible'); |
||
0 ignored issues
–
show
|
|||
106 | var left = (loginFieldPos) ? loginFieldPos.left : passwordFieldPos.left; |
||
107 | var top = (loginFieldPos) ? loginFieldPos.top : passwordFieldPos.top; |
||
108 | var maxZ = getMaxZ(); |
||
109 | |||
110 | if (loginFieldPos && passwordFieldPos.top > loginFieldPos.top) { |
||
111 | //console.log('login fields below each other') |
||
112 | top = passwordFieldPos.top + passwordField.height() + 10; |
||
113 | } else { |
||
114 | // console.log('login fields next to each other') |
||
115 | if (loginFieldPos) { |
||
116 | top = top + loginField.height() + 10; |
||
117 | } else { |
||
118 | top = top + passwordField.height() + 10; |
||
119 | } |
||
120 | } |
||
121 | if (!loginFieldVisible) { |
||
122 | left = passwordFieldPos.left; |
||
123 | } |
||
124 | |||
125 | var pickerUrl = API.extension.getURL('/html/inject/password_picker.html'); |
||
126 | |||
127 | var picker = $j('<iframe class="passwordPickerIframe" scrolling="no" height="385" width="350" frameborder="0" src="' + pickerUrl + '"></iframe>'); |
||
128 | picker.css('position', 'absolute'); |
||
129 | picker.css('left', left); |
||
130 | picker.css('z-index', maxZ + 10); |
||
131 | picker.css('top', top); |
||
132 | $j('body').prepend($j(picker)); |
||
133 | activeForm = form; |
||
134 | // picker.css('width', $j(form).width()); |
||
135 | $j('.passwordPickerIframe:not(:last)').remove(); |
||
136 | } |
||
137 | |||
138 | function onFormIconClick(e) { |
||
139 | e.preventDefault(); |
||
140 | e.stopPropagation(); |
||
141 | var offsetX = e.offsetX; |
||
142 | var offsetRight = (e.data.width - offsetX); |
||
143 | if (offsetRight < e.data.height) { |
||
144 | showPasswordPicker(e.data.form); |
||
145 | } |
||
146 | } |
||
147 | |||
148 | function createFormIcon(el, form) { |
||
149 | var offset = el.offset(); |
||
0 ignored issues
–
show
|
|||
150 | var width = el.width(); |
||
151 | var height = el.height() * 1; |
||
152 | var margin = (el.css('margin')) ? parseInt(el.css('margin').replace('px', '')) : 0; |
||
0 ignored issues
–
show
|
|||
153 | var padding = (el.css('padding')) ? parseInt(el.css('padding').replace('px', '')) : 0; |
||
0 ignored issues
–
show
|
|||
154 | |||
155 | var pickerIcon = API.extension.getURL('/icons/icon.svg'); |
||
156 | $j(el).css('background-image', 'url("' + pickerIcon + '")'); |
||
157 | $j(el).css('background-repeat', 'no-repeat'); |
||
158 | //$j(el).css('background-position', ''); |
||
159 | $j(el).css('cssText', el.attr('style') + ' background-position: right 3px center !important;'); |
||
160 | |||
161 | $j(el).unbind('click', onFormIconClick); |
||
162 | $j(el).click({width: width, height: height, form: form}, onFormIconClick); |
||
163 | } |
||
164 | |||
165 | function createPasswordPicker(form) { |
||
166 | for (var i = 0; i < form.length; i++) { |
||
167 | var el = $j(form[i]); |
||
168 | createFormIcon(el, form); |
||
169 | } |
||
170 | } |
||
171 | |||
172 | function formSubmitted(fields) { |
||
173 | var user = fields[0].value; |
||
174 | var pass = fields[1].value; |
||
175 | var params = { |
||
176 | username: user, |
||
177 | password: pass |
||
178 | }; |
||
179 | //Disable password mining |
||
180 | //$j(fields[1]).attr('type', 'hidden'); |
||
181 | API.runtime.sendMessage(API.runtime.id, {method: "minedForm", args: params}); |
||
182 | |||
183 | } |
||
184 | |||
185 | function inIframe() { |
||
186 | try { |
||
187 | return window.self !== window.top; |
||
188 | } catch (e) { |
||
189 | return true; |
||
190 | } |
||
191 | } |
||
192 | |||
193 | function showDoorhanger(data) { |
||
194 | if (inIframe()) { |
||
195 | return; |
||
196 | } |
||
197 | data.data.currentLocation = window.location.href; |
||
198 | API.runtime.sendMessage(API.runtime.id, {method: "setDoorhangerData", args: data}); |
||
199 | var pickerUrl = API.extension.getURL('/html/inject/doorhanger.html'); |
||
200 | |||
201 | var doorhanger = $j('<iframe id="password-toolbarIframe" style="display: none;" scrolling="no" height="60" width="100%" frameborder="0" src="' + pickerUrl + '"></iframe>'); |
||
202 | $j('#password-toolbarIframe').remove(); |
||
203 | doorhanger.css('z-index', getMaxZ() + 1); |
||
204 | $j('body').prepend(doorhanger); |
||
205 | $j('#password-toolbarIframe').fadeIn(); |
||
206 | } |
||
207 | |||
208 | _this.showDoorhanger = showDoorhanger; |
||
209 | |||
210 | function showUrlUpdateDoorhanger(data) { |
||
211 | var buttons = ['cancel', 'updateUrl']; |
||
212 | showDoorhanger({ |
||
213 | data: data.data, |
||
214 | buttons: buttons |
||
215 | }); |
||
216 | } |
||
217 | |||
218 | _this.showUrlUpdateDoorhanger = showUrlUpdateDoorhanger; |
||
219 | |||
220 | function checkForMined() { |
||
221 | if (inIframe()) { |
||
222 | return; |
||
223 | } |
||
224 | |||
225 | API.runtime.sendMessage(API.runtime.id, {method: "getMinedData"}).then(function (data) { |
||
226 | if (!data) { |
||
227 | return; |
||
228 | } |
||
229 | if (data.hasOwnProperty('username') && data.hasOwnProperty('password') && data.hasOwnProperty('url')) { |
||
230 | var buttons = ['cancel', 'ignore', 'save']; |
||
231 | showDoorhanger({data: data, buttons: buttons}); |
||
232 | } |
||
233 | }); |
||
234 | } |
||
235 | |||
236 | |||
237 | function closeDoorhanger() { |
||
238 | $j('#password-toolbarIframe').hide(400); |
||
239 | $j('#password-toolbarIframe').remove(); |
||
240 | } |
||
241 | |||
242 | _this.closeDoorhanger = closeDoorhanger; |
||
243 | |||
244 | function initForms() { |
||
245 | API.runtime.sendMessage(API.runtime.id, {method: 'getRuntimeSettings'}).then(function (settings) { |
||
246 | var enablePasswordPicker = settings.enablePasswordPicker; |
||
247 | var url = window.location.href; |
||
248 | var loginFields = getLoginFields(); |
||
249 | if (loginFields.length > 0) { |
||
250 | for (var i = 0; i < loginFields.length; i++) { |
||
251 | var form = getFormFromElement(loginFields[i][0]); |
||
252 | if (enablePasswordPicker) { |
||
253 | createPasswordPicker(loginFields[i], form); |
||
0 ignored issues
–
show
|
|||
254 | } |
||
255 | //Password miner |
||
256 | /* jshint ignore:start */ |
||
257 | if (!settings.hasOwnProperty('ignored_sites') || settings.ignored_sites.findUrl(url) !== -1) { |
||
258 | $j(form).submit((function (loginFields) { |
||
259 | return function () { |
||
260 | formSubmitted(loginFields); |
||
261 | }; |
||
262 | })(loginFields[i])); |
||
263 | } |
||
264 | /* jshint ignore:end */ |
||
265 | } |
||
266 | |||
267 | API.runtime.sendMessage(API.runtime.id, { |
||
268 | method: "getCredentialsByUrl", |
||
269 | args: url |
||
270 | }).then(function (logins) { |
||
271 | console.log('Found ' + logins.length + ' logins for this site'); |
||
0 ignored issues
–
show
|
|||
272 | if (logins.length === 1) { |
||
273 | API.runtime.sendMessage(API.runtime.id, {method: 'isAutoFillEnabled'}).then(function (isEnabled) { |
||
274 | if (isEnabled) { |
||
275 | enterLoginDetails(logins[0], false); |
||
276 | } |
||
277 | }); |
||
278 | } |
||
279 | |||
280 | }); |
||
281 | } |
||
282 | |||
283 | }); |
||
284 | } |
||
285 | |||
286 | function minedLoginSaved(args) { |
||
287 | // If the login added by the user then this is true |
||
288 | if (args.selfAdded) { |
||
289 | enterLoginDetails(args.credential, false); |
||
290 | } |
||
291 | } |
||
292 | |||
293 | _this.minedLoginSaved = minedLoginSaved; |
||
294 | |||
295 | function resizeIframe(height) { |
||
296 | $j('#password-toolbarIframe').height(60 + height); |
||
297 | } |
||
298 | |||
299 | _this.resizeIframe = resizeIframe; |
||
300 | |||
301 | function copyText(text) { |
||
302 | var txtToCopy = document.createElement('input'); |
||
303 | txtToCopy.style.left = '-300px'; |
||
304 | txtToCopy.style.position = 'absolute'; |
||
305 | txtToCopy.value = text; |
||
306 | document.body.appendChild(txtToCopy); |
||
307 | txtToCopy.select(); |
||
308 | document.execCommand('copy'); |
||
309 | txtToCopy.parentNode.removeChild(txtToCopy); |
||
310 | } |
||
311 | |||
312 | _this.copyText = copyText; |
||
313 | |||
314 | function init() { |
||
315 | checkForMined(); |
||
316 | initForms(); |
||
317 | } |
||
318 | |||
319 | var readyStateCheckInterval = setInterval(function () { |
||
320 | if (document.readyState === "complete") { |
||
321 | clearInterval(readyStateCheckInterval); |
||
322 | API.runtime.sendMessage(API.runtime.id, {method: 'getMasterPasswordSet'}).then(function (result) { |
||
323 | if (result) { |
||
324 | init(); |
||
325 | var body = document.getElementsByTagName('body')[0]; |
||
326 | observeDOM(body, initForms); |
||
327 | } else { |
||
328 | console.log('[Passman extension] Stopping, vault key not set'); |
||
0 ignored issues
–
show
|
|||
329 | } |
||
330 | }); |
||
331 | } |
||
332 | }, 10); |
||
333 | |||
334 | API.runtime.onMessage.addListener(function (msg, sender) { |
||
335 | //console.log('Method call', msg.method); |
||
336 | if (_this[msg.method]) { |
||
337 | _this[msg.method](msg.args, sender); |
||
338 | } |
||
339 | }); |
||
340 | }); |
||
341 |