Completed
Push — master ( 77b6c1...ce224c )
by Sander
01:54
created

$j.ready   A

Complexity

Conditions 2
Paths 3

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
c 1
b 0
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 = (login.username.trim() !== '' ) ? login.username : login.email;
20
21
        fillPassword(username, login.password);
22
        if ($j('.passwordPickerIframe').is(':visible')) {
23
            removePasswordPicker();
24
        }
25
    }
26
27
    _this.enterLoginDetails = enterLoginDetails;
28
29
30
    function showPasswordPicker(form) {
31
        if ($j('.passwordPickerIframe').length > 1) {
32
            return;
33
        }
34
        var loginField = $j(form[0]);
35
        var loginFieldPos = loginField.offset();
36
        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...
37
        var passwordField = $j(form[1]);
38
        var passwordFieldPos = passwordField.offset();
39
40
        var left = loginFieldPos.left;
41
        var top = loginFieldPos.top;
42
        var maxZ = Math.max.apply(null,
43
            $j.map($j('body *'), function(e) {
44
                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...
45
                    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...
46
            }));
47
        if (passwordFieldPos.top > loginFieldPos.top) {
48
            //console.log('login fields below each other')
49
            top = passwordFieldPos.top + passwordField.height() + 10;
50
51
        } else {
52
            // console.log('login fields next to each other')
53
            top = top + loginField.height() + 10;
54
        }
55
56
57
        var pickerUrl = API.extension.getURL('/html/inject/password_picker.html');
58
59
        var picker = $j('<iframe class="passwordPickerIframe" scrolling="no" height="400" width="350" frameborder="0" src="' + pickerUrl + '"></iframe>');
60
        picker.css('position', 'absolute');
61
        picker.css('left', left);
62
        picker.css('z-index', maxZ);
63
        picker.css('top', top);
64
        $j('body').append($j(picker));
65
        // picker.css('width', $j(form).width());
66
        $j('.passwordPickerIframe:not(:last)').remove();
67
    }
68
69
    function createFormIcon(el, form) {
70
        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...
71
        var width = el.width();
72
        var height = el.height() * 1;
73
        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...
74
        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...
75
76
        var pickerIcon = API.extension.getURL('/icons/icon.svg');
77
        $j(el).css('background-image', 'url("' + pickerIcon + '")');
78
        $j(el).css('background-repeat', 'no-repeat');
79
        $j(el).css('background-position', 'right 3px center');
80
81
82
        function onClick(e) {
83
            e.preventDefault();
84
            var offsetX = e.offsetX;
85
            var offsetRight = (width - offsetX);
86
            if (offsetRight < height) {
87
                showPasswordPicker(form);
88
            }
89
        }
90
91
        // $j(el).bind('click', onClick);
92
        $j(el).click(onClick);
93
94
    }
95
96
    function createPasswordPicker(form) {
97
        for (var i = 0; i < form.length; i++) {
98
            var el = $j(form[i]);
99
            createFormIcon(el, form);
100
101
        }
102
    }
103
104
    function formSubmitted(fields) {
105
        var user = fields[0].value;
106
        var pass = fields[1].value;
107
        var params = {
108
            username: user,
109
            password: pass
110
        };
111
        //Disable password mining
112
        //$j(fields[1]).attr('type', 'hidden');
113
        API.runtime.sendMessage(API.runtime.id, {method: "minedForm", args: params});
114
115
    }
116
117
    function inIframe() {
118
        try {
119
            return window.self !== window.top;
120
        } catch (e) {
121
            return true;
122
        }
123
    }
124
125
    function showDoorhanger(data) {
126
        var buttons = data.buttons;
127
        data = data.data;
128
        if (inIframe()) {
129
            return;
130
        }
131
        var doorhanger_div = $j('<div id="password-toolbar" style="display: none;">');
132
        $j('<span>', {
133
            class: 'toolbar-text',
134
            text: data.title + ' ' + data.username + ' at ' + data.url
135
        }).appendTo(doorhanger_div);
136
137
138
        $j.each(buttons, function (k, button) {
139
            var html_button = $j('<button class="passman-btn passnman-btn-success"></button>').text(button.text);
140
            html_button.click(button.onClickFn);
141
            doorhanger_div.append(html_button);
142
        });
143
144
145
        $j('#password-toolbar').remove();
146
        $j('body').append(doorhanger_div);
147
        $j('#password-toolbar').slideDown();
148
    }
149
150
    _this.showDoorhanger = showDoorhanger;
151
152
    function showUrlUpdateDoorhanger(data) {
153
        var buttons = [
154
            {
155
                text: 'Cancel',
156
                onClickFn: function () {
157
                    $j('#password-toolbar').slideUp();
158
                }
159
            },
160
            {
161
                text: 'Update',
162
                onClickFn: function () {
163
                    //closeToolbar();
164
                    API.runtime.sendMessage(API.runtime.id, {method: "updateCredentialUrl", args: data.data});
165
                    $j('#password-toolbar').find('.toolbar-text').text('Saving...');
166
                    $j('#password-toolbar').find('.passman-btn').hide();
167
                }
168
            }
169
        ];
170
        showDoorhanger({
171
            data: data.data,
172
            buttons: buttons
173
        });
174
    }
175
176
    _this.showUrlUpdateDoorhanger = showUrlUpdateDoorhanger;
177
178
    function checkForMined() {
179
        if (inIframe()) {
180
            return;
181
        }
182
183
184
        API.runtime.sendMessage(API.runtime.id, {method: "getMinedData"}).then(function (data) {
185
            if (!data) {
186
                return;
187
            }
188
            if (data.hasOwnProperty('username') && data.hasOwnProperty('password') && data.hasOwnProperty('url')) {
189
                var btnText = (data.guid === null) ? 'Save' : 'Update';
190
191
                var buttons = [
192
                    {
193
                        text: 'Cancel',
194
                        onClickFn: function () {
195
                            closeToolbar();
196
                            API.runtime.sendMessage(API.runtime.id, {method: "clearMined"});
197
                        }
198
                    },
199
                    {
200
                        text: btnText,
201
                        onClickFn: function () {
202
                            //closeToolbar();
203
                            API.runtime.sendMessage(API.runtime.id, {method: "saveMined"});
204
                            $j('#password-toolbar').find('.toolbar-text').text('Saving...');
205
                            $j('#password-toolbar').find('.passman-btn').hide();
206
                        }
207
                    },
208
                    {
209
                        text: 'Ignore site',
210
                        onClickFn: function () {
211
                            //closeToolbar();
212
                            API.runtime.sendMessage(API.runtime.id, {method: "ignoreSite", args: window.location.href});
213
                            $j('#password-toolbar').find('.toolbar-text').text('Site ignored');
214
                            $j('#password-toolbar').find('.passman-btn').hide();
215
                            setTimeout(function () {
216
                                closeToolbar();
217
                            }, 3000);
218
                        }
219
                    }
220
221
                ];
222
                showDoorhanger({data: data, buttons: buttons});
223
            }
224
        });
225
    }
226
227
    function minedLoginSaved(args) {
228
        // If the login added by the user then this is true
229
        if (args.selfAdded) {
230
            enterLoginDetails(args.credential);
231
            return;
232
        }
233
        if ($j('#password-toolbar').is(':visible')) {
234
            var action = (args.updated) ? 'updated' : 'saved';
235
            $j('#password-toolbar').html('Credential ' + action + '!');
236
            setTimeout(function () {
237
                closeToolbar();
238
            }, 2500);
239
        }
240
    }
241
242
    _this.minedLoginSaved = minedLoginSaved;
243
244
    function closeToolbar() {
245
        $j('#password-toolbar').slideUp(400, function () {
246
            $j('#password-toolbar').remove();
247
        });
248
    }
249
250
    function initForms(){
251
        API.runtime.sendMessage(API.runtime.id, {method: 'getRuntimeSettings'}).then(function (result) {
252
            var disablePasswordPicker = result.disablePasswordPicker;
253
            var url = window.location.href;
254
            var loginFields = getLoginFields();
255
            if (loginFields.length > 0) {
256
                for (var i = 0; i < loginFields.length; i++) {
257
                    var form = getFormFromElement(loginFields[i][0]);
258
                    if (!disablePasswordPicker) {
259
                        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...
260
                    }
261
                    //Password miner
262
                    /* jshint ignore:start */
263
                    if(!result.hasOwnProperty('ignored_sites') || result.ignored_sites.findUrl(url) !== -1 ) {
264
                        $j(form).submit((function (loginFields) {
265
                            return function () {
266
                                formSubmitted(loginFields);
267
                            };
268
                        })(loginFields[i]));
269
                    }
270
                    /* jshint ignore:end */
271
                }
272
273
                API.runtime.sendMessage(API.runtime.id, {
274
                    method: "getCredentialsByUrl",
275
                    args: url
276
                }).then(function (logins) {
277
                    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...
278
                    if (logins.length === 1) {
279
                        API.runtime.sendMessage(API.runtime.id, {method: 'isAutoFillEnabled'}).then(function (isEnabled) {
280
                            if (isEnabled) {
281
                                enterLoginDetails(logins[0]);
282
                            }
283
                        });
284
                    }
285
286
                });
287
            }
288
289
        });
290
    }
291
292
    function init() {
293
        checkForMined();
294
        initForms();
295
    }
296
297
    var readyStateCheckInterval = setInterval(function () {
298
        if (document.readyState === "complete") {
299
            clearInterval(readyStateCheckInterval);
300
            API.runtime.sendMessage(API.runtime.id, {method: 'getMasterPasswordSet'}).then(function (result) {
301
                if (result) {
302
                    init();
303
                    // var body = document.getElementsByTagName('body')[0];
304
                    // observeDOM(body, function () {
305
                    //     initForms();
306
                    // });
307
                } else {
308
                    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...
309
                }
310
            });
311
        }
312
    }, 10);
313
314
    API.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
0 ignored issues
show
Unused Code introduced by
The parameter sendResponse is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
315
        //console.log('Method call', msg.method);
316
        if (_this[msg.method]) {
317
            _this[msg.method](msg.args, sender);
318
        }
319
    });
320
});