blob: 1c18d1981ace0509c84ead59efb2769128795e49 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview
* 'all-sites' is the polymer element for showing the list of all sites under
* Site Settings.
*/
Polymer({
is: 'all-sites',
behaviors: [SiteSettingsBehavior, WebUIListenerBehavior],
properties: {
/**
* Array of sites to display in the widget.
* @type {!Array<!SiteException>}
*/
sites: {
type: Array,
value: function() {
return [];
},
},
},
/** @override */
ready: function() {
this.browserProxy_ =
settings.SiteSettingsPrefsBrowserProxyImpl.getInstance();
this.addWebUIListener(
'contentSettingSitePermissionChanged', this.populateList_.bind(this));
this.populateList_();
},
/**
* Retrieves a list of all known sites with site details.
* @return {!Promise<!Array<!RawSiteException>>}
* @private
*/
getAllSitesList_: function() {
/** @type {!Array<!RawSiteException>} */
const promiseList = [];
const types = Object.values(settings.ContentSettingsTypes);
for (let i = 0; i < types.length; i++) {
const type = types[i];
// <if expr="not chromeos">
if (type == settings.ContentSettingsTypes.PROTECTED_CONTENT)
continue;
// </if>
if (type == settings.ContentSettingsTypes.PROTOCOL_HANDLERS ||
type == settings.ContentSettingsTypes.USB_DEVICES ||
type == settings.ContentSettingsTypes.ZOOM_LEVELS) {
// Some categories store their data in a custom way.
continue;
}
promiseList.push(this.browserProxy_.getExceptionList(type));
}
return Promise.all(promiseList);
},
/**
* A handler for selecting a site (by clicking on the origin).
* @param {!{model: !{item: !SiteException}}} event
* @private
*/
onOriginTap_: function(event) {
settings.navigateTo(
settings.routes.SITE_SETTINGS_SITE_DETAILS,
new URLSearchParams('site=' + event.model.item.origin));
},
/** @private */
populateList_: function() {
this.getAllSitesList_().then(this.processExceptions_.bind(this));
},
/**
* Process the exception list returned from the native layer.
* @param {!Array<!RawSiteException>} data List of sites (exceptions)
* to process.
* @private
*/
processExceptions_: function(data) {
const sites = /** @type {!Array<!RawSiteException>} */ ([]);
for (let i = 0; i < data.length; ++i) {
const exceptionList = data[i];
for (let k = 0; k < exceptionList.length; ++k) {
sites.push(exceptionList[k]);
}
}
this.sites = this.toSiteArray_(sites);
},
/**
* TODO(dschuyler): Move this processing to C++ handler.
* Converts a list of exceptions received from the C++ handler to
* full SiteException objects. The list is sorted by site name, then protocol
* and port and de-duped (by origin).
* @param {!Array<!RawSiteException>} sites A list of sites to convert.
* @return {!Array<!SiteException>} A list of full SiteExceptions. Sorted and
* deduped.
* @private
*/
toSiteArray_: function(sites) {
const self = this;
sites.sort(function(a, b) {
const url1 = self.toUrl(a.origin);
const url2 = self.toUrl(b.origin);
let comparison = url1.host.localeCompare(url2.host);
if (comparison == 0) {
comparison = url1.protocol.localeCompare(url2.protocol);
if (comparison == 0) {
comparison = url1.port.localeCompare(url2.port);
if (comparison == 0) {
// Compare hosts for the embedding origins.
let host1 = self.toUrl(a.embeddingOrigin);
let host2 = self.toUrl(b.embeddingOrigin);
host1 = (host1 == null) ? '' : host1.host;
host2 = (host2 == null) ? '' : host2.host;
return host1.localeCompare(host2);
}
}
}
return comparison;
});
const results = /** @type {!Array<!SiteException>} */ ([]);
let lastOrigin = '';
let lastEmbeddingOrigin = '';
for (let i = 0; i < sites.length; ++i) {
// Remove duplicates.
if (sites[i].origin == lastOrigin &&
sites[i].embeddingOrigin == lastEmbeddingOrigin) {
continue;
}
/** @type {!SiteException} */
const siteException = this.expandSiteException(sites[i]);
results.push(siteException);
lastOrigin = siteException.origin;
lastEmbeddingOrigin = siteException.embeddingOrigin;
}
return results;
},
});