Completed
Pull Request — master (#121)
by Sander
41s
created

$j.ready   A

Complexity

Conditions 2
Paths 3

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 2
c 1
b 1
f 0
nc 3
nop 1
dl 0
loc 4
rs 10
1
/* global API */
2
var $j = jQuery.noConflict();
3
4
$j(document).ready(function () {
5
    var _this = this;
6
    Array.prototype.findUrl = function (match) {
0 ignored issues
show
Compatibility Best Practice introduced by
You are extending the built-in type Array. This may have unintended consequences on other objects using this built-in type. Consider subclassing instead.
Loading history...
7
        return this.filter(function (item) {
8
            return typeof item === 'string' && item.indexOf(match) > -1;
9
        });
10
    };
11
12
    function removePasswordPicker() {
13
        $j('.passwordPickerIframe').remove();
14
    }
15
16
    _this.removePasswordPicker = removePasswordPicker;
17
18
    function enterLoginDetails(login) {
19
        var username;
20
21
        if (login.hasOwnProperty('username')) {
22
            username = (login.username !== '' ) ? login.username : login.email;
23
        }
24
        if(!username){
25
            username = null;
26
        }
27
28
        fillPassword(username, login.password);
29
        if ($j('.passwordPickerIframe').is(':visible')) {
30
            removePasswordPicker();
31
        }
32
    }
33
34
    _this.enterLoginDetails = enterLoginDetails;
35
36
    function getMaxZ() {
37
        return Math.max.apply(null,
38
            $j.map($j('body *'), function (e) {
39
                if ($j(e).css('position') !== 'static')
0 ignored issues
show
Complexity Best Practice introduced by
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 return statement is found in some execution paths, but not in all.

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 isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
40
                    return parseInt($j(e).css('z-index')) || 1;
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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...
41
            }));
42
    }
43
44
    function showPasswordPicker(form) {
45
        if ($j('.passwordPickerIframe').length > 1) {
46
            return;
47
        }
48
        var loginField = $j(form[0]);
49
        var loginFieldPos = loginField.offset();
50
        var loginFieldVisible = loginField.is(':visible');
51
52
        var position = $j(form[1]).position();
0 ignored issues
show
Unused Code introduced by
The assignment to variable position seems to be never used. Consider removing it.
Loading history...
53
        var passwordField = $j(form[1]);
54
        var passwordFieldPos = passwordField.offset();
55
        var passwordFieldVisible = loginField.is(':visible');
0 ignored issues
show
Unused Code introduced by
The variable passwordFieldVisible seems to be never used. Consider removing it.
Loading history...
56
        var left = (loginFieldPos) ? loginFieldPos.left : passwordFieldPos.left;
57
        var top = (loginFieldPos) ? loginFieldPos.top : passwordFieldPos.top;
58
        var maxZ = getMaxZ();
59
60
        if (loginFieldPos && passwordFieldPos.top > loginFieldPos.top) {
61
            //console.log('login fields below each other')
62
            top = passwordFieldPos.top + passwordField.height() + 10;
63
        } else {
64
            // console.log('login fields next to each other')
65
            if(loginFieldPos){
66
                top =  top + loginField.height() + 10;
67
            } else {
68
                top =  top + passwordField.height() + 10;
69
            }
70
        }
71
        if(!loginFieldVisible){
72
            left = passwordFieldPos.left;
73
        }
74
75
        var pickerUrl = API.extension.getURL('/html/inject/password_picker.html');
76
77
        var picker = $j('<iframe class="passwordPickerIframe" scrolling="no" height="385" width="350" frameborder="0" src="' + pickerUrl + '"></iframe>');
78
        picker.css('position', 'absolute');
79
        picker.css('left', left);
80
        picker.css('z-index', maxZ + 10);
81
        picker.css('top', top);
82
        $j('body').prepend($j(picker));
83
        // picker.css('width', $j(form).width());
84
        $j('.passwordPickerIframe:not(:last)').remove();
85
    }
86
87
    function createFormIcon(el, form) {
88
        var offset = el.offset();
0 ignored issues
show
Unused Code introduced by
The assignment to variable offset seems to be never used. Consider removing it.
Loading history...
89
        var width = el.width();
90
        var height = el.height() * 1;
91
        var margin = (el.css('margin')) ? parseInt(el.css('margin').replace('px', '')) : 0;
0 ignored issues
show
Unused Code introduced by
The variable margin seems to be never used. Consider removing it.
Loading history...
92
        var padding = (el.css('padding')) ? parseInt(el.css('padding').replace('px', '')) : 0;
0 ignored issues
show
Unused Code introduced by
The variable padding seems to be never used. Consider removing it.
Loading history...
93
94
        var pickerIcon = API.extension.getURL('/icons/icon.svg');
95
        $j(el).css('background-image', 'url("' + pickerIcon + '")');
96
        $j(el).css('background-repeat', 'no-repeat');
97
        //$j(el).css('background-position', '');
98
        $j(el).css('cssText', el.attr('style')+' background-position: right 3px center !important;');
99
100
101
        function onClick(e) {
102
            e.preventDefault();
103
            var offsetX = e.offsetX;
104
            var offsetRight = (width - offsetX);
105
            if (offsetRight < height) {
106
                showPasswordPicker(form);
107
            }
108
        }
109
110
        // $j(el).bind('click', onClick);
111
        $j(el).click(onClick);
112
113
    }
114
115
    function createPasswordPicker(form) {
116
        for (var i = 0; i < form.length; i++) {
117
            var el = $j(form[i]);
118
            createFormIcon(el, form);
119
120
        }
121
    }
122
123
    function formSubmitted(fields) {
124
        var user = fields[0].value;
125
        var pass = fields[1].value;
126
        var params = {
127
            username: user,
128
            password: pass
129
        };
130
        //Disable password mining
131
        //$j(fields[1]).attr('type', 'hidden');
132
        API.runtime.sendMessage(API.runtime.id, {method: "minedForm", args: params});
133
134
    }
135
136
    function inIframe() {
137
        try {
138
            return window.self !== window.top;
139
        } catch (e) {
140
            return true;
141
        }
142
    }
143
144
    function showDoorhanger(data) {
145
        if (inIframe()) {
146
            return;
147
        }
148
        data.data.currentLocation = window.location.href;
149
        API.runtime.sendMessage(API.runtime.id, {method: "setDoorhangerData", args: data});
150
        var pickerUrl = API.extension.getURL('/html/inject/doorhanger.html');
151
152
        var doorhanger = $j('<iframe id="password-toolbarIframe" style="display: none;" scrolling="no" height="60" width="100%" frameborder="0" src="' + pickerUrl + '"></iframe>');
153
        $j('#password-toolbarIframe').remove();
154
        doorhanger.css('z-index',  getMaxZ() + 1);
155
        $j('body').prepend(doorhanger);
156
        $j('#password-toolbarIframe').fadeIn();
157
    }
158
159
    _this.showDoorhanger = showDoorhanger;
160
161
    function showUrlUpdateDoorhanger(data) {
162
        var buttons = ['cancel', 'updateUrl'];
163
        showDoorhanger({
164
            data: data.data,
165
            buttons: buttons
166
        });
167
    }
168
169
    _this.showUrlUpdateDoorhanger = showUrlUpdateDoorhanger;
170
171
    function checkForMined() {
172
        if (inIframe()) {
173
            return;
174
        }
175
176
        API.runtime.sendMessage(API.runtime.id, {method: "getMinedData"}).then(function (data) {
177
            if (!data) {
178
                return;
179
            }
180
            if (data.hasOwnProperty('username') && data.hasOwnProperty('password') && data.hasOwnProperty('url')) {
181
                var buttons = [ 'cancel', 'ignore', 'save' ];
182
                showDoorhanger({data: data, buttons: buttons});
183
            }
184
        });
185
    }
186
187
188
    function closeDoorhanger() {
189
        $j('#password-toolbarIframe').hide(400);
190
        $j('#password-toolbarIframe').remove();
191
    }
192
193
    _this.closeDoorhanger = closeDoorhanger;
194
195
    function initForms() {
196
        API.runtime.sendMessage(API.runtime.id, {method: 'getRuntimeSettings'}).then(function (settings) {
197
            var disablePasswordPicker = settings.disablePasswordPicker;
198
            var url = window.location.href;
199
            var loginFields = getLoginFields();
200
            if (loginFields.length > 0) {
201
                for (var i = 0; i < loginFields.length; i++) {
202
                    var form = getFormFromElement(loginFields[i][0]);
203
                    if (!disablePasswordPicker) {
204
                        createPasswordPicker(loginFields[i], form);
0 ignored issues
show
Bug introduced by
The call to createPasswordPicker seems to have too many arguments starting with form.
Loading history...
205
                    }
206
                    //Password miner
207
                    /* jshint ignore:start */
208
                    if (!settings.hasOwnProperty('ignored_sites') || settings.ignored_sites.findUrl(url) !== -1) {
209
                        $j(form).submit((function (loginFields) {
210
                            return function () {
211
                                formSubmitted(loginFields);
212
                            };
213
                        })(loginFields[i]));
214
                    }
215
                    /* jshint ignore:end */
216
                }
217
218
                API.runtime.sendMessage(API.runtime.id, {
219
                    method: "getCredentialsByUrl",
220
                    args: url
221
                }).then(function (logins) {
222
                    console.log('Found ' + logins.length + ' logins for this site');
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
223
                    if (logins.length === 1) {
224
                        API.runtime.sendMessage(API.runtime.id, {method: 'isAutoFillEnabled'}).then(function (isEnabled) {
225
                            if (isEnabled) {
226
                                enterLoginDetails(logins[0]);
227
                            }
228
                        });
229
                    }
230
231
                });
232
            }
233
234
        });
235
    }
236
237
    function minedLoginSaved(args) {
238
        // If the login added by the user then this is true
239
        if (args.selfAdded) {
240
            enterLoginDetails(args.credential);
241
        }
242
    }
243
244
    _this.minedLoginSaved = minedLoginSaved;
245
246
    function resizeIframe(height) {
247
        $j('#password-toolbarIframe').height(60 + height);
248
    }
249
250
    _this.resizeIframe = resizeIframe;
251
252
    function copyText(text) {
253
        var txtToCopy = document.createElement('input');
254
        txtToCopy.style.left = '-300px';
255
        txtToCopy.style.position = 'absolute';
256
        txtToCopy.value = text;
257
        document.body.appendChild(txtToCopy);
258
        txtToCopy.select();
259
        document.execCommand('copy');
260
        txtToCopy.parentNode.removeChild(txtToCopy);
261
    }
262
263
    _this.copyText = copyText;
264
265
    function init() {
266
        checkForMined();
267
        initForms();
268
    }
269
270
    var readyStateCheckInterval = setInterval(function () {
271
        if (document.readyState === "complete") {
272
            clearInterval(readyStateCheckInterval);
273
            API.runtime.sendMessage(API.runtime.id, {method: 'getMasterPasswordSet'}).then(function (result) {
274
                if (result) {
275
                    init();
276
                    var body = document.getElementsByTagName('body')[0];
0 ignored issues
show
Unused Code introduced by
The variable body seems to be never used. Consider removing it.
Loading history...
277
                    // observeDOM(body, function () {
278
                    //     initForms();
279
                    // });
280
                } else {
281
                    console.log('[Passman extension] Stopping, vault key not set');
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
282
                }
283
            });
284
        }
285
    }, 10);
286
287
    API.runtime.onMessage.addListener(function (msg, sender) {
288
        //console.log('Method call', msg.method);
289
        if (_this[msg.method]) {
290
            _this[msg.method](msg.args, sender);
291
        }
292
    });
293
});
294