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.
6 * HSTS is HTTPS Strict Transport Security: a way for sites to elect to always
7 * use HTTPS. See http://dev.chromium.org/sts
9 * This UI allows a user to query and update the browser's list of HSTS domains.
10 * It also allows users to query and update the browser's list of public key
14 var HSTSView = (function() {
17 // We inherit from DivView.
18 var superClass = DivView;
24 assertFirstConstructorCall(HSTSView);
26 // Call superclass's constructor.
27 superClass.call(this, HSTSView.MAIN_BOX_ID);
29 this.addInput_ = $(HSTSView.ADD_INPUT_ID);
30 this.addStsCheck_ = $(HSTSView.ADD_STS_CHECK_ID);
31 this.addPkpCheck_ = $(HSTSView.ADD_PKP_CHECK_ID);
32 this.addPins_ = $(HSTSView.ADD_PINS_ID);
33 this.deleteInput_ = $(HSTSView.DELETE_INPUT_ID);
34 this.queryInput_ = $(HSTSView.QUERY_INPUT_ID);
35 this.queryOutputDiv_ = $(HSTSView.QUERY_OUTPUT_DIV_ID);
37 var form = $(HSTSView.ADD_FORM_ID);
38 form.addEventListener('submit', this.onSubmitAdd_.bind(this), false);
40 form = $(HSTSView.DELETE_FORM_ID);
41 form.addEventListener('submit', this.onSubmitDelete_.bind(this), false);
43 form = $(HSTSView.QUERY_FORM_ID);
44 form.addEventListener('submit', this.onSubmitQuery_.bind(this), false);
46 g_browser.addHSTSObserver(this);
49 HSTSView.TAB_ID = 'tab-handle-hsts';
50 HSTSView.TAB_NAME = 'HSTS';
51 HSTSView.TAB_HASH = '#hsts';
53 // IDs for special HTML elements in hsts_view.html
54 HSTSView.MAIN_BOX_ID = 'hsts-view-tab-content';
55 HSTSView.ADD_INPUT_ID = 'hsts-view-add-input';
56 HSTSView.ADD_STS_CHECK_ID = 'hsts-view-check-sts-input';
57 HSTSView.ADD_PKP_CHECK_ID = 'hsts-view-check-pkp-input';
58 HSTSView.ADD_PINS_ID = 'hsts-view-add-pins';
59 HSTSView.ADD_FORM_ID = 'hsts-view-add-form';
60 HSTSView.ADD_SUBMIT_ID = 'hsts-view-add-submit';
61 HSTSView.DELETE_INPUT_ID = 'hsts-view-delete-input';
62 HSTSView.DELETE_FORM_ID = 'hsts-view-delete-form';
63 HSTSView.DELETE_SUBMIT_ID = 'hsts-view-delete-submit';
64 HSTSView.QUERY_INPUT_ID = 'hsts-view-query-input';
65 HSTSView.QUERY_OUTPUT_DIV_ID = 'hsts-view-query-output';
66 HSTSView.QUERY_FORM_ID = 'hsts-view-query-form';
67 HSTSView.QUERY_SUBMIT_ID = 'hsts-view-query-submit';
69 cr.addSingletonGetter(HSTSView);
71 HSTSView.prototype = {
72 // Inherit the superclass's methods.
73 __proto__: superClass.prototype,
75 onSubmitAdd_: function(event) {
76 g_browser.sendHSTSAdd(this.addInput_.value,
77 this.addStsCheck_.checked,
78 this.addPkpCheck_.checked,
80 g_browser.sendHSTSQuery(this.addInput_.value);
81 this.queryInput_.value = this.addInput_.value;
82 this.addStsCheck_.checked = false;
83 this.addPkpCheck_.checked = false;
84 this.addInput_.value = '';
85 this.addPins_.value = '';
86 event.preventDefault();
89 onSubmitDelete_: function(event) {
90 g_browser.sendHSTSDelete(this.deleteInput_.value);
91 this.deleteInput_.value = '';
92 event.preventDefault();
95 onSubmitQuery_: function(event) {
96 g_browser.sendHSTSQuery(this.queryInput_.value);
97 event.preventDefault();
100 onHSTSQueryResult: function(result) {
101 if (result.error != undefined) {
102 this.queryOutputDiv_.innerHTML = '';
103 var s = addNode(this.queryOutputDiv_, 'span');
104 s.textContent = result.error;
105 s.style.color = '#e00';
106 yellowFade(this.queryOutputDiv_);
110 if (result.result == false) {
111 this.queryOutputDiv_.innerHTML = '<b>Not found</b>';
112 yellowFade(this.queryOutputDiv_);
116 this.queryOutputDiv_.innerHTML = '';
118 var s = addNode(this.queryOutputDiv_, 'span');
119 s.innerHTML = '<b>Found:</b><br/>';
123 addTextNode(this.queryOutputDiv_, ' domain: ');
124 t = addNodeWithText(this.queryOutputDiv_, 'tt', result.domain);
125 b = addNode(this.queryOutputDiv_, 'br');
127 addTextNode(this.queryOutputDiv_, ' static_upgrade_mode: ');
128 t = addNodeWithText(this.queryOutputDiv_, 'tt',
129 modeToString(result.static_upgrade_mode));
130 b = addNode(this.queryOutputDiv_, 'br');
132 addTextNode(this.queryOutputDiv_, ' static_sts_include_subdomains: ');
133 t = addNodeWithText(this.queryOutputDiv_, 'tt',
134 result.static_sts_include_subdomains);
135 b = addNode(this.queryOutputDiv_, 'br');
137 addTextNode(this.queryOutputDiv_, ' static_pkp_include_subdomains: ');
138 t = addNodeWithText(this.queryOutputDiv_, 'tt',
139 result.static_pkp_include_subdomains);
140 b = addNode(this.queryOutputDiv_, 'br');
142 addTextNode(this.queryOutputDiv_, ' static_sts_observed: ');
143 t = addNodeWithText(this.queryOutputDiv_, 'tt',
144 result.static_sts_observed);
145 b = addNode(this.queryOutputDiv_, 'br');
147 addTextNode(this.queryOutputDiv_, ' static_pkp_observed: ');
148 t = addNodeWithText(this.queryOutputDiv_, 'tt',
149 result.static_pkp_observed);
150 b = addNode(this.queryOutputDiv_, 'br');
152 addTextNode(this.queryOutputDiv_, ' static_spki_hashes: ');
153 t = addNode(this.queryOutputDiv_, 'tt');
155 // |public_key_hashes| is an old synonym for what is now
156 // |preloaded_spki_hashes|, which in turn is a legacy synonym for
157 // |static_spki_hashes|.
158 if (typeof result.public_key_hashes === 'undefined')
159 result.public_key_hashes = '';
160 if (typeof result.preloaded_spki_hashes === 'undefined')
161 result.preloaded_spki_hashes = '';
162 if (typeof result.static_spki_hashes === 'undefined')
163 result.static_spki_hashes = '';
166 if (result.public_key_hashes)
167 hashes.push(result.public_key_hashes);
168 if (result.preloaded_spki_hashes)
169 hashes.push(result.preloaded_spki_hashes);
170 if (result.static_spki_hashes)
171 hashes.push(result.static_spki_hashes);
173 t.textContent = hashes.join(',');
174 b = addNode(this.queryOutputDiv_, 'br');
176 addTextNode(this.queryOutputDiv_, ' dynamic_upgrade_mode: ');
177 t = addNodeWithText(this.queryOutputDiv_, 'tt',
178 modeToString(result.dynamic_upgrade_mode));
179 b = addNode(this.queryOutputDiv_, 'br');
181 addTextNode(this.queryOutputDiv_, ' dynamic_sts_include_subdomains: ');
182 t = addNodeWithText(this.queryOutputDiv_, 'tt',
183 result.dynamic_sts_include_subdomains || '');
184 b = addNode(this.queryOutputDiv_, 'br');
186 addTextNode(this.queryOutputDiv_, ' dynamic_pkp_include_subdomains: ');
187 t = addNodeWithText(this.queryOutputDiv_, 'tt',
188 result.dynamic_pkp_include_subdomains || '');
189 b = addNode(this.queryOutputDiv_, 'br');
191 addTextNode(this.queryOutputDiv_, ' dynamic_sts_observed: ');
192 t = addNodeWithText(this.queryOutputDiv_, 'tt',
193 result.dynamic_sts_observed || '');
194 b = addNode(this.queryOutputDiv_, 'br');
196 addTextNode(this.queryOutputDiv_, ' dynamic_pkp_observed: ');
197 t = addNodeWithText(this.queryOutputDiv_, 'tt',
198 result.dynamic_pkp_observed || '');
199 b = addNode(this.queryOutputDiv_, 'br');
201 addTextNode(this.queryOutputDiv_, ' dynamic_spki_hashes: ');
202 t = addNodeWithText(this.queryOutputDiv_, 'tt',
203 result.dynamic_spki_hashes || '');
205 yellowFade(this.queryOutputDiv_);
209 function modeToString(m) {
210 // These numbers must match those in
211 // TransportSecurityState::DomainState::UpgradeMode.
215 return 'OPPORTUNISTIC';
221 function yellowFade(element) {
222 element.style.webkitTransitionProperty = 'background-color';
223 element.style.webkitTransitionDuration = '0';
224 element.style.backgroundColor = '#fffccf';
225 setTimeout(function() {
226 element.style.webkitTransitionDuration = '1000ms';
227 element.style.backgroundColor = '#fff';