1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5cr.define('options.internet', function() {
6  /** @const */ var EditableTextField = options.EditableTextField;
7
8  /**
9   * The regular expression that matches an IP address. String to match against
10   * should have all whitespace stripped already.
11   * @const
12   * @type {RegExp}
13   */
14  var singleIp_ = /^([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)$/;
15
16  /**
17   * Creates a new field specifically for entering IP addresses.
18   * @constructor
19   */
20  function IPAddressField() {
21    var el = cr.doc.createElement('div');
22    IPAddressField.decorate(el);
23    return el;
24  }
25
26  /**
27   * Decorates an element as a inline-editable list item. Note that this is
28   * a subclass of IPAddressField.
29   * @param {!HTMLElement} el The element to decorate.
30   */
31  IPAddressField.decorate = function(el) {
32    el.__proto__ = IPAddressField.prototype;
33    el.decorate();
34  };
35
36  IPAddressField.prototype = {
37    __proto__: EditableTextField.prototype,
38
39    /** @override */
40    decorate: function() {
41      EditableTextField.prototype.decorate.call(this);
42    },
43
44    /**
45     * Indicates whether or not empty values are allowed.
46     * @type {boolean}
47     */
48    get allowEmpty() {
49      return this.hasAttribute('allow-empty');
50    },
51
52    /** @override */
53    get currentInputIsValid() {
54      if (!this.editField.value && this.allowEmpty)
55        return true;
56
57      // Make sure it's only got numbers and ".", there are the correct
58      // count of them, and they are all within the correct range.
59      var fieldValue = this.editField.value.replace(/\s/g, '');
60      var matches = singleIp_.exec(fieldValue);
61      var rangeCorrect = true;
62      if (matches != null) {
63        for (var i = 1; i < matches.length; ++i) {
64          var value = parseInt(matches[i], 10);
65          if (value < 0 || value > 255) {
66            rangeCorrect = false;
67            break;
68          }
69        }
70      }
71      return this.editField.validity.valid && matches != null &&
72          rangeCorrect && matches.length == 5;
73    },
74
75    /** @override */
76    get hasBeenEdited() {
77      return this.editField.value != this.model.value;
78    },
79
80    /**
81     * Overrides superclass to mutate the input during a successful commit. For
82     * the purposes of entering IP addresses, this just means stripping off
83     * whitespace and leading zeros from each of the octets so that they conform
84     * to the normal format for IP addresses.
85     * @override
86     * @param {string} value Input IP address to be mutated.
87     * @return {string} mutated IP address.
88     */
89    mutateInput: function(value) {
90      if (!value)
91        return value;
92
93      var fieldValue = value.replace(/\s/g, '');
94      var matches = singleIp_.exec(fieldValue);
95      var result = [];
96
97      // If we got this far, matches shouldn't be null, but make sure.
98      if (matches != null) {
99        // starting at one because the first match element contains the entire
100        // match, and we don't care about that.
101        for (var i = 1; i < matches.length; ++i)
102          result.push(parseInt(matches[i], 10));
103      }
104      return result.join('.');
105    },
106  };
107
108  return {
109    IPAddressField: IPAddressField,
110  };
111});
112