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>: mode: ';
121 // TODO(palmer): Combine these 2-line pairs into 1:
122 // addNodeWithText(this.queryOutputDiv_, 'tt', results.sts_observed);
123 var t
= addNode(this.queryOutputDiv_
, 'tt');
124 t
.textContent
= modeToString(result
.mode
);
126 addTextNode(this.queryOutputDiv_
, ' sts_include_subdomains:');
128 t
= addNode(this.queryOutputDiv_
, 'tt');
129 t
.textContent
= result
.sts_subdomains
;
131 addTextNode(this.queryOutputDiv_
, ' pkp_include_subdomains:');
133 t
= addNode(this.queryOutputDiv_
, 'tt');
134 t
.textContent
= result
.pkp_subdomains
;
136 addTextNode(this.queryOutputDiv_
, ' sts_observed:');
138 t
= addNode(this.queryOutputDiv_
, 'tt');
139 t
.textContent
= result
.sts_observed
;
141 addTextNode(this.queryOutputDiv_
, ' pkp_observed:');
143 t
= addNode(this.queryOutputDiv_
, 'tt');
144 t
.textContent
= result
.pkp_observed
;
146 addTextNode(this.queryOutputDiv_
, ' domain:');
148 t
= addNode(this.queryOutputDiv_
, 'tt');
149 t
.textContent
= result
.domain
;
151 addTextNode(this.queryOutputDiv_
, ' pubkey_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|. Look for all three, and also for
158 // |dynamic_spki_hashes|.
159 if (typeof result
.public_key_hashes
=== 'undefined')
160 result
.public_key_hashes
= '';
161 if (typeof result
.preloaded_spki_hashes
=== 'undefined')
162 result
.preloaded_spki_hashes
= '';
163 if (typeof result
.static_spki_hashes
=== 'undefined')
164 result
.static_spki_hashes
= '';
165 if (typeof result
.dynamic_spki_hashes
=== 'undefined')
166 result
.dynamic_spki_hashes
= '';
169 if (result
.public_key_hashes
)
170 hashes
.push(result
.public_key_hashes
);
171 if (result
.preloaded_spki_hashes
)
172 hashes
.push(result
.preloaded_spki_hashes
);
173 if (result
.static_spki_hashes
)
174 hashes
.push(result
.static_spki_hashes
);
175 if (result
.dynamic_spki_hashes
)
176 hashes
.push(result
.dynamic_spki_hashes
);
178 t
.textContent
= hashes
.join(',');
179 yellowFade(this.queryOutputDiv_
);
183 function modeToString(m
) {
184 // These numbers must match those in
185 // TransportSecurityState::DomainState::UpgradeMode.
189 return 'OPPORTUNISTIC';
195 function yellowFade(element
) {
196 element
.style
.webkitTransitionProperty
= 'background-color';
197 element
.style
.webkitTransitionDuration
= '0';
198 element
.style
.backgroundColor
= '#fffccf';
199 setTimeout(function() {
200 element
.style
.webkitTransitionDuration
= '1000ms';
201 element
.style
.backgroundColor
= '#fff';