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/>';
122 'domain', 'static_upgrade_mode', 'static_sts_include_subdomains',
123 'static_pkp_include_subdomains', 'static_sts_observed',
124 'static_pkp_observed', 'static_spki_hashes', 'dynamic_upgrade_mode',
125 'dynamic_sts_include_subdomains', 'dynamic_pkp_include_subdomains',
126 'dynamic_sts_observed', 'dynamic_pkp_observed', 'dynamic_spki_hashes'
129 var kStaticHashKeys
= [
130 'public_key_hashes', 'preloaded_spki_hashes', 'static_spki_hashes'
133 var staticHashes
= [];
134 for (var i
= 0; i
< kStaticHashKeys
.length
; ++i
) {
135 var staticHashValue
= result
[kStaticHashKeys
[i
]];
136 if (staticHashValue
!= undefined && staticHashValue
!= '')
137 staticHashes
.push(staticHashValue
);
140 for (var i
= 0; i
< keys
.length
; ++i
) {
142 var value
= result
[key
];
143 addTextNode(this.queryOutputDiv_
, ' ' + key
+ ': ');
145 // If there are no static_hashes, do not make it seem like there is a
146 // static PKP policy in place.
147 if (staticHashes
.length
== 0 && key
.indexOf('static_pkp_') == 0) {
148 addNode(this.queryOutputDiv_
, 'br');
152 if (key
=== 'static_spki_hashes') {
153 addNodeWithText(this.queryOutputDiv_
, 'tt', staticHashes
.join(','));
154 } else if (key
.indexOf('_upgrade_mode') >= 0) {
155 addNodeWithText(this.queryOutputDiv_
, 'tt', modeToString(value
));
157 addNodeWithText(this.queryOutputDiv_
, 'tt',
158 value
== undefined ? '' : value
);
160 addNode(this.queryOutputDiv_
, 'br');
163 yellowFade(this.queryOutputDiv_
);
167 function modeToString(m
) {
168 // These numbers must match those in
169 // TransportSecurityState::DomainState::UpgradeMode.
173 return 'OPPORTUNISTIC';
179 function yellowFade(element
) {
180 element
.style
.webkitTransitionProperty
= 'background-color';
181 element
.style
.webkitTransitionDuration
= '0';
182 element
.style
.backgroundColor
= '#fffccf';
183 setTimeout(function() {
184 element
.style
.webkitTransitionDuration
= '1000ms';
185 element
.style
.backgroundColor
= '#fff';