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.
5 // Include test fixture.
6 GEN_INCLUDE(['net_internals_test.js']);
12 * A valid hash that can be set for a domain.
15 var VALID_HASH = 'sha1/Guzek9lMwR3KeIS8wwS9gBvVtIg=';
18 * An invalid hash that can't be set for a domain.
21 var INVALID_HASH = 'invalid';
24 * Possible results of an HSTS query.
27 var QueryResultType = {
34 * A Task that waits for the results of an HSTS query. Once the results are
35 * received, checks them before completing. Does not initiate the query.
36 * @param {string} domain The domain expected in the returned results.
37 * @param {bool} stsSubdomains Whether or not the stsSubdomains flag is expected
38 * to be set in the returned results. Ignored on error and not found
40 * @param {bool} pkpSubdomains Whether or not the pkpSubdomains flag is expected
41 * to be set in the returned results. Ignored on error and not found
43 * @param {number} stsObserved The time the STS policy was observed.
44 * @param {number} pkpObserved The time the PKP policy was observed.
45 * @param {string} publicKeyHashes Expected public key hashes. Ignored on error
46 * error and not found results.
47 * @param {QueryResultType} queryResultType The expected result type of the
48 * results of the query.
49 * @extends {NetInternalsTest.Task}
51 function CheckQueryResultTask(domain, stsSubdomains, pkpSubdomains,
52 stsObserved, pkpObserved, publicKeyHashes,
54 this.domain_ = domain;
55 this.stsSubdomains_ = stsSubdomains;
56 this.pkpSubdomains_ = pkpSubdomains;
57 this.stsObserved_ = stsObserved;
58 this.pkpObserved_ = pkpObserved;
59 this.publicKeyHashes_ = publicKeyHashes;
60 this.queryResultType_ = queryResultType;
61 NetInternalsTest.Task.call(this);
64 CheckQueryResultTask.prototype = {
65 __proto__: NetInternalsTest.Task.prototype,
68 * Starts watching for the query results.
71 g_browser.addHSTSObserver(this);
75 * Callback from the BrowserBridge. Validates |result| and completes the
77 * @param {object} result Results from the query.
79 onHSTSQueryResult: function(result) {
80 // Ignore results after |this| is finished.
82 expectEquals(this.domain_, $(HSTSView.QUERY_INPUT_ID).value);
84 // Each case has its own validation function because of the design of the
85 // test reporting infrastructure.
86 if (result.error != undefined) {
87 this.checkError_(result);
88 } else if (!result.result) {
89 this.checkNotFound_(result);
91 this.checkSuccess_(result);
93 this.running_ = false;
95 // Start the next task asynchronously, so it can add another HSTS observer
96 // without getting the current result.
97 window.setTimeout(this.onTaskDone.bind(this), 1);
102 * On errors, checks the result.
103 * @param {object} result Results from the query.
105 checkError_: function(result) {
106 expectEquals(QueryResultType.ERROR, this.queryResultType_);
107 expectEquals(result.error, $(HSTSView.QUERY_OUTPUT_DIV_ID).innerText);
111 * Checks the result when the entry was not found.
112 * @param {object} result Results from the query.
114 checkNotFound_: function(result) {
115 expectEquals(QueryResultType.NOT_FOUND, this.queryResultType_);
116 expectEquals('Not found', $(HSTSView.QUERY_OUTPUT_DIV_ID).innerText);
120 * Checks successful results.
121 * @param {object} result Results from the query.
123 checkSuccess_: function(result) {
124 expectEquals(QueryResultType.SUCCESS, this.queryResultType_);
125 expectEquals(this.stsSubdomains_, result.dynamic_sts_include_subdomains);
126 expectEquals(this.pkpSubdomains_, result.dynamic_pkp_include_subdomains);
127 // Disabled because of http://crbug.com/397639
128 // expectLE(this.stsObserved_, result.dynamic_sts_observed);
129 // expectLE(this.pkpObserved_, result.dynamic_pkp_observed);
131 // |public_key_hashes| is an old synonym for what is now
132 // |preloaded_spki_hashes|, which in turn is a legacy synonym for
133 // |static_spki_hashes|. Look for all three, and also for
134 // |dynamic_spki_hashes|.
135 if (typeof result.public_key_hashes === 'undefined')
136 result.public_key_hashes = '';
137 if (typeof result.preloaded_spki_hashes === 'undefined')
138 result.preloaded_spki_hashes = '';
139 if (typeof result.static_spki_hashes === 'undefined')
140 result.static_spki_hashes = '';
141 if (typeof result.dynamic_spki_hashes === 'undefined')
142 result.dynamic_spki_hashes = '';
145 if (result.public_key_hashes)
146 hashes.push(result.public_key_hashes);
147 if (result.preloaded_spki_hashes)
148 hashes.push(result.preloaded_spki_hashes);
149 if (result.static_spki_hashes)
150 hashes.push(result.static_spki_hashes);
151 if (result.dynamic_spki_hashes)
152 hashes.push(result.dynamic_spki_hashes);
154 expectEquals(this.publicKeyHashes_, hashes.join(','));
156 // Verify that the domain appears somewhere in the displayed text.
157 outputText = $(HSTSView.QUERY_OUTPUT_DIV_ID).innerText;
158 expectLE(0, outputText.search(this.domain_));
163 * A Task to try and add an HSTS domain via the HTML form. The task will wait
164 * until the results from the automatically sent query have been received, and
165 * then checks them against the expected values.
166 * @param {string} domain The domain to send and expected to be returned.
167 * @param {bool} stsSubdomains Whether the HSTS subdomain checkbox should be
168 * selected. Also the corresponding expected return value, in the success
170 * @param {bool} pkpSubdomains Whether the pinning subdomain checkbox should be
171 * selected. Also the corresponding expected return value, in the success
173 * @param {number} stsObserved The time the STS policy was observed.
174 * @param {number} pkpObserved The time the PKP policy was observed.
175 * @param {string} publicKeyHashes Public key hash to send. Also the
176 * corresponding expected return value, on success. When this is the string
177 * INVALID_HASH, an empty string is expected to be received instead.
178 * @param {QueryResultType} queryResultType Expected result type.
179 * @extends {CheckQueryResultTask}
181 function AddTask(domain, stsSubdomains, pkpSubdomains, publicKeyHashes,
182 stsObserved, pkpObserved, queryResultType) {
183 this.requestedPublicKeyHashes_ = publicKeyHashes;
184 if (publicKeyHashes == INVALID_HASH)
185 publicKeyHashes = '';
186 CheckQueryResultTask.call(this, domain, stsSubdomains, pkpSubdomains,
187 stsObserved, pkpObserved, publicKeyHashes,
191 AddTask.prototype = {
192 __proto__: CheckQueryResultTask.prototype,
195 * Fills out the add form, simulates a click to submit it, and starts
196 * listening for the results of the query that is automatically submitted.
199 $(HSTSView.ADD_INPUT_ID).value = this.domain_;
200 $(HSTSView.ADD_STS_CHECK_ID).checked = this.stsSubdomains_;
201 $(HSTSView.ADD_PKP_CHECK_ID).checked = this.pkpSubdomains_;
202 $(HSTSView.ADD_PINS_ID).value = this.requestedPublicKeyHashes_;
203 $(HSTSView.ADD_SUBMIT_ID).click();
204 CheckQueryResultTask.prototype.start.call(this);
209 * A Task to query a domain and wait for the results. Parameters mirror those
210 * of CheckQueryResultTask, except |domain| is also the name of the domain to
212 * @extends {CheckQueryResultTask}
214 function QueryTask(domain, stsSubdomains, pkpSubdomains, stsObserved,
215 pkpObserved, publicKeyHashes, queryResultType) {
216 CheckQueryResultTask.call(this, domain, stsSubdomains, pkpSubdomains,
217 stsObserved, pkpObserved, publicKeyHashes,
221 QueryTask.prototype = {
222 __proto__: CheckQueryResultTask.prototype,
225 * Fills out the query form, simulates a click to submit it, and starts
226 * listening for the results.
229 CheckQueryResultTask.prototype.start.call(this);
230 $(HSTSView.QUERY_INPUT_ID).value = this.domain_;
231 $(HSTSView.QUERY_SUBMIT_ID).click();
236 * Task that deletes a single domain, then queries the deleted domain to make
238 * @param {string} domain The domain to delete.
239 * @param {QueryResultType} queryResultType The result of the query. Can be
240 * QueryResultType.ERROR or QueryResultType.NOT_FOUND.
241 * @extends {QueryTask}
243 function DeleteTask(domain, queryResultType) {
244 expectNotEquals(queryResultType, QueryResultType.SUCCESS);
245 this.domain_ = domain;
246 QueryTask.call(this, domain, false, false, '', 0, 0, queryResultType);
249 DeleteTask.prototype = {
250 __proto__: QueryTask.prototype,
253 * Fills out the delete form and simulates a click to submit it. Then sends
257 $(HSTSView.DELETE_INPUT_ID).value = this.domain_;
258 $(HSTSView.DELETE_SUBMIT_ID).click();
259 QueryTask.prototype.start.call(this);
264 * Checks that querying a domain that was never added fails.
266 TEST_F('NetInternalsTest', 'netInternalsHSTSViewQueryNotFound', function() {
267 NetInternalsTest.switchToView('hsts');
268 taskQueue = new NetInternalsTest.TaskQueue(true);
269 var now = new Date().getTime() / 1000.0;
270 taskQueue.addTask(new QueryTask('somewhere.com', false, false, now, now, '',
271 QueryResultType.NOT_FOUND));
276 * Checks that querying a domain with an invalid name returns an error.
278 TEST_F('NetInternalsTest', 'netInternalsHSTSViewQueryError', function() {
279 NetInternalsTest.switchToView('hsts');
280 taskQueue = new NetInternalsTest.TaskQueue(true);
281 var now = new Date().getTime() / 1000.0;
282 taskQueue.addTask(new QueryTask('\u3024', false, false, now, now, '',
283 QueryResultType.ERROR));
288 * Deletes a domain that was never added.
290 TEST_F('NetInternalsTest', 'netInternalsHSTSViewDeleteNotFound', function() {
291 NetInternalsTest.switchToView('hsts');
292 taskQueue = new NetInternalsTest.TaskQueue(true);
293 taskQueue.addTask(new DeleteTask('somewhere.com', QueryResultType.NOT_FOUND));
298 * Deletes a domain that returns an error on lookup.
300 TEST_F('NetInternalsTest', 'netInternalsHSTSViewDeleteError', function() {
301 NetInternalsTest.switchToView('hsts');
302 taskQueue = new NetInternalsTest.TaskQueue(true);
303 taskQueue.addTask(new DeleteTask('\u3024', QueryResultType.ERROR));
308 * Adds a domain and then deletes it.
310 TEST_F('NetInternalsTest', 'netInternalsHSTSViewAddDelete', function() {
311 NetInternalsTest.switchToView('hsts');
312 taskQueue = new NetInternalsTest.TaskQueue(true);
313 var now = new Date().getTime() / 1000.0;
314 taskQueue.addTask(new AddTask('somewhere.com', false, false, VALID_HASH,
315 now, now, QueryResultType.SUCCESS));
316 taskQueue.addTask(new DeleteTask('somewhere.com', QueryResultType.NOT_FOUND));
321 * Tries to add a domain with an invalid name.
323 TEST_F('NetInternalsTest', 'netInternalsHSTSViewAddFail', function() {
324 NetInternalsTest.switchToView('hsts');
325 taskQueue = new NetInternalsTest.TaskQueue(true);
326 var now = new Date().getTime() / 1000.0;
327 taskQueue.addTask(new AddTask('0123456789012345678901234567890' +
328 '012345678901234567890123456789012345',
329 false, false, '', now, now,
330 QueryResultType.NOT_FOUND));
335 * Tries to add a domain with a name that errors out on lookup due to having
336 * non-ASCII characters in it.
338 TEST_F('NetInternalsTest', 'netInternalsHSTSViewAddError', function() {
339 NetInternalsTest.switchToView('hsts');
340 taskQueue = new NetInternalsTest.TaskQueue(true);
341 var now = new Date().getTime() / 1000.0;
342 taskQueue.addTask(new AddTask('\u3024', false, false, '', now, now,
343 QueryResultType.ERROR));
348 * Adds a domain with an invalid hash.
350 TEST_F('NetInternalsTest', 'netInternalsHSTSViewAddInvalidHash', function() {
351 NetInternalsTest.switchToView('hsts');
352 taskQueue = new NetInternalsTest.TaskQueue(true);
353 var now = new Date().getTime() / 1000.0;
354 taskQueue.addTask(new AddTask('somewhere.com', true, true, INVALID_HASH,
355 now, now, QueryResultType.SUCCESS));
356 taskQueue.addTask(new DeleteTask('somewhere.com', QueryResultType.NOT_FOUND));
361 * Adds the same domain twice in a row, modifying some values the second time.
363 TEST_F('NetInternalsTest', 'netInternalsHSTSViewAddOverwrite', function() {
364 NetInternalsTest.switchToView('hsts');
365 taskQueue = new NetInternalsTest.TaskQueue(true);
366 var now = new Date().getTime() / 1000.0;
367 taskQueue.addTask(new AddTask('somewhere.com', true, true, VALID_HASH,
368 now, now, QueryResultType.SUCCESS));
369 taskQueue.addTask(new AddTask('somewhere.com', false, false, '',
370 now, now, QueryResultType.SUCCESS));
371 taskQueue.addTask(new DeleteTask('somewhere.com', QueryResultType.NOT_FOUND));
376 * Adds two different domains and then deletes them.
378 TEST_F('NetInternalsTest', 'netInternalsHSTSViewAddTwice', function() {
379 NetInternalsTest.switchToView('hsts');
380 taskQueue = new NetInternalsTest.TaskQueue(true);
381 var now = new Date().getTime() / 1000.0;
382 taskQueue.addTask(new AddTask('somewhere.com', false, false, VALID_HASH,
383 now, now, QueryResultType.SUCCESS));
384 taskQueue.addTask(new QueryTask('somewhereelse.com', false, false, now, now,
385 '', QueryResultType.NOT_FOUND));
386 taskQueue.addTask(new AddTask('somewhereelse.com', true, true, '',
387 now, now, QueryResultType.SUCCESS));
388 taskQueue.addTask(new QueryTask('somewhere.com', false, false, now, now,
389 VALID_HASH, QueryResultType.SUCCESS));
390 taskQueue.addTask(new DeleteTask('somewhere.com', QueryResultType.NOT_FOUND));
391 taskQueue.addTask(new QueryTask('somewhereelse.com', true, true, now, now, '',
392 QueryResultType.SUCCESS));
393 taskQueue.addTask(new DeleteTask('somewhereelse.com',
394 QueryResultType.NOT_FOUND));
398 })(); // Anonymous namespace