Completed
Push — master ( f1ca89...451677 )
by Sander
01:05
created

$j.ready   A

Complexity

Conditions 1
Paths 2

Size

Total Lines 48

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
c 2
b 0
f 0
nc 2
nop 0
dl 0
loc 48
rs 9.125
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' && match.indexOf(item) > -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.trim() !== '' ) ? login.username : login.email;
23
        }
24
25
        fillPassword(username, login.password);
0 ignored issues
show
Bug introduced by
The variable username does not seem to be initialized in case login.hasOwnProperty("username") on line 21 is false. Are you sure the function fillPassword handles undefined variables?
Loading history...
26
        if ($j('.passwordPickerIframe').is(':visible')) {
27
            removePasswordPicker();
28
        }
29
    }
30
31
    _this.enterLoginDetails = enterLoginDetails;
32
33
34
    function showPasswordPicker(form) {
35
        if ($j('.passwordPickerIframe').length > 1) {
36
            return;
37
        }
38
        var loginField = $j(form[0]);
39
        var loginFieldPos = loginField.offset();
40
        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...
41
        var passwordField = $j(form[1]);
42
        var passwordFieldPos = passwordField.offset();
43
44
        var left = loginFieldPos.left;
45
        var top = loginFieldPos.top;
46
        var maxZ = Math.max.apply(null,
47
            $j.map($j('body *'), function (e) {
48
                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...
49
                    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...
50
            }));
51
        if (passwordFieldPos.top > loginFieldPos.top) {
52
            //console.log('login fields below each other')
53
            top = passwordFieldPos.top + passwordField.height() + 10;
54
55
        } else {
56
            // console.log('login fields next to each other')
57
            top = top + loginField.height() + 10;
58
        }
59
60
61
        var pickerUrl = API.extension.getURL('/html/inject/password_picker.html');
62
63
        var picker = $j('<iframe class="passwordPickerIframe" scrolling="no" height="400" width="350" frameborder="0" src="' + pickerUrl + '"></iframe>');
64
        picker.css('position', 'absolute');
65
        picker.css('left', left);
66
        picker.css('z-index', maxZ);
67
        picker.css('top', top);
68
        $j('body').append($j(picker));
69
        // picker.css('width', $j(form).width());
70
        $j('.passwordPickerIframe:not(:last)').remove();
71
    }
72
73
    function createFormIcon(el, form) {
74
        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...
75
        var width = el.width();
76
        var height = el.height() * 1;
77
        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...
78
        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...
79
80
        var pickerIcon = API.extension.getURL('/icons/icon.svg');
81
        $j(el).css('background-image', 'url("' + pickerIcon + '")');
82
        $j(el).css('background-repeat', 'no-repeat');
83
        $j(el).css('background-position', 'right 3px center');
84
85
86
        function onClick(e) {
87
            e.preventDefault();
88
            var offsetX = e.offsetX;
89
            var offsetRight = (width - offsetX);
90
            if (offsetRight < height) {
91
                showPasswordPicker(form);
92
            }
93
        }
94
95
        // $j(el).bind('click', onClick);
96
        $j(el).click(onClick);
97
98
    }
99
100
    function createPasswordPicker(form) {
101
        for (var i = 0; i < form.length; i++) {
102
            var el = $j(form[i]);
103
            createFormIcon(el, form);
104
105
        }
106
    }
107
108
    function formSubmitted(form, fields) {
109
        var user = fields[0].value;
110
        var pass = fields[1].value;
111
        var params = {
112
            username: user,
113
            password: pass
114
        };
115
        $j(form).attr('scraped', true);
116
        //Disable password mining
117
        //$j(fields[1]).attr('type', 'hidden');
118
        API.runtime.sendMessage(API.runtime.id, {method: "minedForm", args: params});
119
        setTimeout(function () {
120
            $j(form).submit();
121
        }, 100);
122
    }
123
124
    function inIframe() {
125
        try {
126
            return window.self !== window.top;
127
        } catch (e) {
128
            return true;
129
        }
130
    }
131
132
    function showDoorhanger(data) {
133
        if (inIframe()) {
134
            return;
135
        }
136
        data.data.currentLocation = window.location.href;
137
        API.runtime.sendMessage(API.runtime.id, {method: "setDoorhangerData", args: data});
138
        var pickerUrl = API.extension.getURL('/html/inject/doorhanger.html');
139
140
        var doorhanger = $j('<iframe id="password-toolbarIframe" style="display: none;" scrolling="no" height="80" width="100%" frameborder="0" src="' + pickerUrl + '"></iframe>');
141
        $j('#password-toolbarIframe').remove();
142
        $j('body').after(doorhanger);
143
        $j('#password-toolbarIframe').slideDown();
144
    }
145
146
    _this.showDoorhanger = showDoorhanger;
147
148
    function showUrlUpdateDoorhanger(data) {
149
        var buttons = ['cancel', 'updateUrl'];
150
        showDoorhanger({
151
            data: data.data,
152
            buttons: buttons
153
        });
154
    }
155
156
    _this.showUrlUpdateDoorhanger = showUrlUpdateDoorhanger;
157
158
    function checkForMined() {
159
        if (inIframe()) {
160
            return;
161
        }
162
163
        API.runtime.sendMessage(API.runtime.id, {method: "getMinedData"}).then(function (data) {
164
            if (!data) {
165
                return;
166
            }
167
            if (data.hasOwnProperty('username') && data.hasOwnProperty('password') && data.hasOwnProperty('url')) {
168
                var buttons = [ 'cancel', 'save', 'ignore'];
169
                showDoorhanger({data: data, buttons: buttons});
170
            }
171
        });
172
    }
173
174
175
176
    function closeDoorhanger() {
177
        $j('#password-toolbarIframe').slideUp(400, function () {
178
            $j('#password-toolbarIframe').remove();
179
        });
180
    }
181
    _this.closeDoorhanger = closeDoorhanger;
182
183
    function initForms() {
184
        API.runtime.sendMessage(API.runtime.id, {method: 'getRuntimeSettings'}).then(function (result) {
185
            var disablePasswordPicker = result.disablePasswordPicker;
186
            var url = window.location.href;
187
            var loginFields = getLoginFields();
188
            if (loginFields.length > 0) {
189
                for (var i = 0; i < loginFields.length; i++) {
190
                    var form = getFormFromElement(loginFields[i][0]);
191
                    if (!disablePasswordPicker) {
192
                        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...
193
                    }
194
                    //Password miner
195
                    /* jshint ignore:start */
196
                    $j(form).submit(function (e) {
197
                        if(!$j(this).attr('scraped')){
198
                            e.preventDefault();
199
                        }
200
                    });
201
                    if (!result.hasOwnProperty('ignored_sites') || result.ignored_sites.findUrl(url).length === 0) {
202
                        $j(form).submit((function (form, loginFields) {
203
                            return function () {
204
                                formSubmitted(form, loginFields);
205
                            };
206
                        })(form, loginFields[i]));
207
                    }
208
                    /* jshint ignore:end */
209
                }
210
211
                API.runtime.sendMessage(API.runtime.id, {
212
                    method: "getCredentialsByUrl",
213
                    args: url
214
                }).then(function (logins) {
215
                    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...
216
                    if (logins.length === 1) {
217
                        API.runtime.sendMessage(API.runtime.id, {method: 'isAutoFillEnabled'}).then(function (isEnabled) {
218
                            if (isEnabled) {
219
                                enterLoginDetails(logins[0]);
220
                            }
221
                        });
222
                    }
223
224
                });
225
            }
226
227
228
229
        });
230
    }
231
232
    function minedLoginSaved(args) {
233
        // If the login added by the user then this is true
234
        if (args.selfAdded) {
235
            enterLoginDetails(args.credential);
236
        }
237
    }
238
    _this.minedLoginSaved = minedLoginSaved;
239
240
    function copyText(text) {
241
        var txtToCopy = document.createElement('input');
242
        txtToCopy.style.left = '-300px';
243
        txtToCopy.style.position = 'absolute';
244
        txtToCopy.value = text;
245
        document.body.appendChild(txtToCopy);
246
        txtToCopy.select();
247
        document.execCommand('copy');
248
        txtToCopy.parentNode.removeChild(txtToCopy);
249
    }
250
251
    _this.copyText = copyText;
252
253
    function init() {
254
        checkForMined();
255
        initForms();
256
    }
257
258
    var readyStateCheckInterval = setInterval(function () {
259
        if (document.readyState === "complete") {
260
            clearInterval(readyStateCheckInterval);
261
            API.runtime.sendMessage(API.runtime.id, {method: 'getMasterPasswordSet'}).then(function (result) {
262
                if (result) {
263
                    init();
264
                    // var body = document.getElementsByTagName('body')[0];
265
                    // observeDOM(body, function () {
266
                    //     initForms();
267
                    // });
268
                } else {
269
                    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...
270
                }
271
            });
272
        }
273
    }, 10);
274
275
    API.runtime.onMessage.addListener(function (msg, sender) {
276
        //console.log('Method call', msg.method);
277
        if (_this[msg.method]) {
278
            _this[msg.method](msg.args, sender);
279
        }
280
    });
281
});