Completed
Push — master ( 3da151...1147de )
by Sander
01:05
created

js/ui/password_picker/password_picker.js   C

Complexity

Total Complexity 55
Complexity/F 1.38

Size

Lines of Code 298
Function Count 40

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 1 Features 0
Metric Value
cc 0
c 4
b 1
f 0
nc 8
dl 0
loc 298
rs 6.3333
wmc 55
mnd 2
bc 58
fnc 40
bpm 1.45
cpm 1.375
noi 2

How to fix   Complexity   

Complexity

Complex classes like js/ui/password_picker/password_picker.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
$(document).ready(function () {
2
    var _this = this;
3
    var storage = new API.Storage();
4
5
6
    function fillLogin(login) {
7
        API.runtime.sendMessage(API.runtime.id, {
8
            method: 'passToParent',
9
            args: {
10
                injectMethod: 'enterLoginDetails',
11
                args: login
12
            }
13
        });
14
    }
15
16
    function removePasswordPicker(login) {
0 ignored issues
show
Unused Code introduced by
The parameter login 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...
17
        API.runtime.sendMessage(API.runtime.id, {
18
            method: 'passToParent',
19
            args: {
20
                injectMethod: 'removePasswordPicker'
21
            }
22
        });
23
    }
24
25
    function copyTextToClipboard(text) {
26
        var copyFrom = document.createElement("textarea");
27
        copyFrom.textContent = text;
28
        var body = document.getElementsByTagName('body')[0];
29
        body.appendChild(copyFrom);
30
        copyFrom.select();
31
        document.execCommand('copy');
32
        body.removeChild(copyFrom);
33
    }
34
35
    _this.copyTextToClipboard = copyTextToClipboard;
36
37
38
    function setupAddCredentialFields() {
39
        var labelfield = $('#savepw-label');
40
        labelfield.val(document.title);
41
        var userfield = $('#savepw-username');
42
        var pwfield = $('#savepw-password');
43
        $('.togglePw').click(function () {
44
            $('.togglePw').find('.fa').toggleClass('fa-eye').toggleClass('fa-eye-slash');
45
            if (pwfield.attr('type') === 'password') {
46
                pwfield.attr('type', 'text');
47
            } else {
48
                pwfield.attr('type', 'password');
49
            }
50
        });
51
52
        $('#savepw-save').click(function (e) {
53
            e.preventDefault();
54
            $(this).val('Saving...');
55
            $(this).attr('disabled', true);
56
            API.runtime.sendMessage(API.runtime.id, {
57
                method: "injectCreateCredential", args: {
58
                    label: labelfield.val(),
59
                    username: userfield.val(),
60
                    password: pwfield.val()
61
                }
62
            });
63
        });
64
65
        $('#savepw-cancel').click(function () {
66
            labelfield.val(document.title);
67
            userfield.val('');
68
            pwfield.val('');
69
            removePasswordPicker();
70
            //removePasswordPicker();
71
        });
72
73
    }
74
75
    function toggleFieldType(field) {
76
        if ($(field).attr('type').toLowerCase() === 'text') {
77
            $(field).attr('type', 'password');
78
        } else {
79
            $(field).attr('type', 'text');
80
        }
81
    }
82
83
    function genPwd(settings) {
84
        /* jshint ignore:start */
85
        var password = generatePassword(settings['length'],
86
            settings.useUppercase,
87
            settings.useLowercase,
88
            settings.useDigits,
89
            settings.useSpecialChars,
90
            settings.minimumDigitCount,
91
            settings.avoidAmbiguousCharacters,
92
            settings.requireEveryCharType);
93
        /* jshint ignore:end */
94
        return password;
95
    }
96
97
    function getPasswordGenerationSettings(cb) {
98
        var default_settings = {
99
            'length': 12,
100
            'useUppercase': true,
101
            'useLowercase': true,
102
            'useDigits': true,
103
            'useSpecialChars': true,
104
            'minimumDigitCount': 3,
105
            'avoidAmbiguousCharacters': false,
106
            'requireEveryCharType': true
107
        };
108
        storage.get('password_generator_settings').then(function (_settings) {
109
            if (!_settings) {
110
                _settings = default_settings;
111
            }
112
113
            cb(_settings);
114
        }).error(function () {
115
            cb(default_settings);
116
        });
117
    }
118
119
    function setupPasswordGenerator() {
120
        //getPasswordGeneratorSettings
121
        getPasswordGenerationSettings(function (settings) {
122
            var round = 0;
123
124
            function generate_pass(inputId) {
125
                var new_password = genPwd(settings);
126
                $('#' + inputId).val(new_password);
127
                setTimeout(function () {
128
                    if (round < 10) {
129
                        generate_pass(inputId);
130
                        round++;
131
                    } else {
132
                        round = 0;
133
                    }
134
                }, 10);
135
            }
136
137
            $.each(settings, function (setting, val) {
138
                if (typeof(val) === "boolean") {
139
                    $('[name="' + setting + '"]').prop('checked', val);
140
                } else {
141
                    $('[name="' + setting + '"]').val(val);
142
                }
143
            });
144
145
            $('form[name="advancedSettings"]').change(function () {
146
                var pw_settings_form = $(this);
147
                settings = pw_settings_form.serializeObject();
148
                storage.set('password_generator_settings', settings);
149
            });
150
151
            $('.renewpw').click(function () {
152
                generate_pass('generated_password');
153
            });
154
            $('.renewpw_newac').click(function () {
155
                generate_pass('savepw-password');
156
157
            });
158
            $('.renewpw').click();
159
            $('.renewpw_newac').click();
160
161
            $('.usepwd').click(function () {
162
                $('#savepw-password').val($('#generated_password').val());
163
                $('.tab.add').click();
164
            });
165
166
            $('.togglePwVis').click(function () {
167
                toggleFieldType('#generated_password');
168
                $(this).find('.fa').toggleClass('fa-eye-slash').toggleClass('fa-eye');
169
            });
170
171
            $('.adv_opt').click(function () {
172
173
                var adv_settings = $('.pw-setting-advanced');
174
                $(this).find('i').toggleClass('fa-angle-right').toggleClass('fa-angle-down');
175
                if (adv_settings.is(':visible')) {
176
                    adv_settings.slideUp();
177
                } else {
178
                    adv_settings.slideDown();
179
                }
180
            });
181
        });
182
    }
183
184
    var picker = $('#password_picker');
185
    picker.find('.tab').click(function () {
186
        var target = $(this).attr('class').replace('active', '').replace('tab', '').trim();
187
        picker.find('.tab').removeClass('active');
188
        picker.find('.tab-content').children().hide();
189
        picker.find('.tab-' + target + '-content').show();
190
        picker.find('.tab.' + target).addClass('active');
191
    });
192
193
    $('.tab.close').click(function () {
194
        removePasswordPicker();
195
    });
196
197
198
199
200
    API.runtime.sendMessage(API.runtime.id, {method: "getActiveTab", args: {returnFn: "returnActiveTab"}});
201
202
    function returnActiveTab(tab) {
203
        API.runtime.sendMessage(API.runtime.id, {method: "getCredentialsByUrl", args: [tab.url]}).then(function (logins) {
204
            if (logins.length !== 0) {
205
                picker.find('.tab-list-content').html('');
206
            }
207
            for (var i = 0; i < logins.length; i++) {
208
                var login = logins[i];
209
                var div = $('<div>', {class: 'account', text: login.label});
210
                $('<br>').appendTo(div);
211
                var username = (login.username.trim() !== '' ) ? login.username : login.email;
212
                $('<small>').text(username).appendTo(div);
213
                /* jshint ignore:start */
214
                div.click((function (login) {
215
                    return function () {
216
                        //enterLoginDetails(login);
217
                        //API.runtime.sendMessage(API.runtime.id, {method: 'getMasterPasswordSet'})
218
                        fillLogin(login)
219
                    };
220
                })(login));
221
                /* jshint ignore:end*/
222
223
                picker.find('.tab-list-content').append(div);
224
            }
225
        });
226
    }
227
    _this.returnActiveTab = returnActiveTab;
228
229
230
    $('.no-credentials .save').on('click', function () {
231
        $('.tab.add').click();
232
    });
233
    $('.no-credentials .search').on('click', function () {
234
        $('.tab.search').click();
235
    });
236
    $('.no-credentials .gen').on('click', function () {
237
        $('.tab.generate').click();
238
    });
239
    setupAddCredentialFields();
240
    setupPasswordGenerator();
241
242
243
    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...
244
        if (_this[msg.method]) {
245
            _this[msg.method](msg.args, sender);
246
        }
247
    });
248
249
250
251
    $('#password_search').keypress(function(e) {
252
        if(e.which === 13) {
253
            searchCredentials();
254
        }
255
    });
256
257
    function url_domain(data) {
258
        var matches = data.match(/^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
259
        return matches && matches[1];  // domain will be null if no match is found
260
    }
261
262
263
    function searchCredentials() {
264
        $('#searchResults').html('');
265
        var searchText =  $('#password_search').val();
266
        if(searchText === ''){
267
            return;
268
        }
269
        API.runtime.sendMessage(API.runtime.id, {'method': 'searchCredential', args: searchText}).then(function (result) {
270
            if(result.length === 0){
271
                $('#searchResults').html('No results');
272
            }
273
            for (var i = 0; i < result.length; i++) {
274
                var login = result[i];
275
                var div = $('<div>', {class: 'account', text: login.label});
276
                $('<br>').appendTo(div);
277
                var username = (login.username.trim() !== '' ) ? login.username : login.email;
278
                $('<small>').text(username).appendTo(div);
279
                $('<br>').appendTo(div);
280
                $('<small>').text(url_domain(login.url)).appendTo(div);
281
                /* jshint ignore:start */
282
                div.click((function (login) {
283
                    return function () {
284
                        //enterLoginDetails(login);
285
                        //API.runtime.sendMessage(API.runtime.id, {method: 'getMasterPasswordSet'})
286
                        fillLogin(login);
287
                        //@TODO Ask to update the url of the login
288
                        API.runtime.sendMessage(API.runtime.id, {'method': 'updateCredentialUrlDoorhanger', args: login})
289
                    };
290
                })(login));
291
                /* jshint ignore:end*/
292
293
                picker.find('#searchResults').append(div);
294
            }
295
        });
296
    }
297
298
});