blob: 46b1be62226201a035e78fb142975575da548c8f [file] [log] [blame]
// Copyright 2018 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 Utility functions that are used in Cups printer setup dialogs.
*/
cr.define('settings.printing', function() {
/**
* @param {string} protocol
* @return {boolean} Whether |protocol| is a network protocol
*/
function isNetworkProtocol(protocol) {
return ['ipp', 'ipps', 'http', 'https', 'socket', 'lpd'].includes(protocol);
}
/**
* Returns true if the printer's name and address is valid. This function
* uses regular expressions to determine whether the provided printer name
* and address are valid. Address can be either an ipv4/6 address or a
* hostname followed by an optional port.
* NOTE: The regular expression for hostnames will allow hostnames that are
* over 255 characters.
* @param {CupsPrinterInfo} printer
* @return {boolean}
*/
function isNameAndAddressValid(printer) {
if (!printer) {
return false;
}
const name = printer.printerName;
const address = printer.printerAddress;
if (!isNetworkProtocol(printer.printerProtocol) && !!name) {
// We do not need to verify the address of a non-network printer.
return true;
}
if (!name || !address) {
return false;
}
const hostnamePrefix = '([a-z\\d]|[a-z\\d][a-z\\d\\-]{0,61}[a-z\\d])';
// Matches an arbitrary number of 'prefix patterns' which are separated by a
// dot.
const hostnameSuffix = `(\\.${hostnamePrefix})*`;
// Matches an optional port at the end of the address.
const portNumber = '(:\\d+)?';
const ipv6Full = '(([a-f\\d]){1,4}(:(:)?([a-f\\d]){1,4}){1,7})';
// Special cases for addresses using a shorthand notation.
const ipv6Prefix = '(::([a-f\\d]){1,4})';
const ipv6Suffix = '(([a-f\\d]){1,4}::)';
const ipv6Combined = `(${ipv6Full}|${ipv6Prefix}|${ipv6Suffix})`;
const ipv6WithPort = `(\\[${ipv6Combined}\\]${portNumber})`;
// Matches valid hostnames and ipv4 addresses.
const hostnameRegex =
new RegExp(`^${hostnamePrefix}${hostnameSuffix}${portNumber}$`, 'i');
// Matches valid ipv6 addresses.
const ipv6AddressRegex =
new RegExp(`^(${ipv6Combined}|${ipv6WithPort})$`, 'i');
const invalidIpv6Regex = new RegExp('.*::.*::.*');
return hostnameRegex.test(address) ||
(ipv6AddressRegex.test(address) && !invalidIpv6Regex.test(address));
}
/**
* Returns true if the printer's manufacturer and model or ppd path is valid.
* @param {string} manufacturer
* @param {string} model
* @param {string} ppdPath
* @return {boolean}
*/
function isPPDInfoValid(manufacturer, model, ppdPath) {
return !!((manufacturer && model) || ppdPath);
}
/**
* Returns the base name of a filepath.
* @param {string} path The full path of the file
* @return {string} The base name of the file
*/
function getBaseName(path) {
if (path && path.length > 0) {
return path.substring(path.lastIndexOf('/') + 1);
}
return '';
}
/**
* A function used for sorting printer names based on the current locale's
* collation order.
* @param {!CupsPrinterInfo} first
* @param {!CupsPrinterInfo} second
* @return {number} The result of the comparison.
*/
function alphabeticalSort(first, second) {
return first.printerName.toLocaleLowerCase().localeCompare(
second.printerName.toLocaleLowerCase());
}
/**
* Return the error string corresponding to the result code.
* @param {!PrinterSetupResult} result
* @return {string}
*/
function getErrorText(result) {
switch (result) {
case PrinterSetupResult.FATAL_ERROR:
return loadTimeData.getString('printerAddedFatalErrorMessage');
case PrinterSetupResult.PRINTER_UNREACHABLE:
return loadTimeData.getString('printerAddedUnreachableMessage');
case PrinterSetupResult.DBUS_ERROR:
// Simply return a generic error message as this error should only
// occur when a call to Dbus fails which isn't meaningful to the user.
return loadTimeData.getString('printerAddedFailedMessage');
case PrinterSetupResult.NATIVE_PRINTERS_NOT_ALLOWED:
return loadTimeData.getString(
'printerAddedNativePrintersNotAllowedMessage');
case PrinterSetupResult.INVALID_PRINTER_UPDATE:
return loadTimeData.getString('editPrinterInvalidPrinterUpdate');
case PrinterSetupResult.PPD_TOO_LARGE:
return loadTimeData.getString('printerAddedPpdTooLargeMessage');
case PrinterSetupResult.INVALID_PPD:
return loadTimeData.getString('printerAddedInvalidPpdMessage');
case PrinterSetupResult.PPD_NOT_FOUND:
return loadTimeData.getString('printerAddedPpdNotFoundMessage');
case PrinterSetupResult.PPD_UNRETRIEVABLE:
return loadTimeData.getString('printerAddedPpdUnretrievableMessage');
default:
assertNotReached();
}
}
/**
* We sort by printer type, which is based off of a maintained list in
* cups_printers_types.js. If the types are the same, we sort alphabetically.
* @param {!PrinterListEntry} first
* @param {!PrinterListEntry} second
* @return {number}
*/
function sortPrinters(first, second) {
if (first.printerType == second.printerType) {
return settings.printing.alphabeticalSort(
first.printerInfo, second.printerInfo);
}
return first.printerType - second.printerType;
}
/**
* @param {!CupsPrinterInfo} printer
* @param {string} searchTerm
* @return {boolean} True if the printer has |searchTerm| in its name.
*/
function matchesSearchTerm(printer, searchTerm) {
return printer.printerName.toLowerCase().includes(searchTerm.toLowerCase());
}
/**
* @param {!PrinterListEntry} first
* @param {!PrinterListEntry} second
* @return {boolean}
*/
function arePrinterIdsEqual(first, second) {
return first.printerInfo.printerId == second.printerInfo.printerId;
}
return {
isNetworkProtocol: isNetworkProtocol,
isNameAndAddressValid: isNameAndAddressValid,
isPPDInfoValid: isPPDInfoValid,
getBaseName: getBaseName,
alphabeticalSort: alphabeticalSort,
getErrorText: getErrorText,
sortPrinters: sortPrinters,
matchesSearchTerm: matchesSearchTerm,
arePrinterIdsEqual: arePrinterIdsEqual,
};
});