diff options
Diffstat (limited to 'chromium/chrome/browser/ui/webui/settings/chromeos')
5 files changed, 215 insertions, 77 deletions
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc index 9ec43165c6a..a75305fab98 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc @@ -48,6 +48,9 @@ namespace settings { namespace { +// usb:// is 6 characters long. +constexpr int kUsbSchemeLength = 6; + constexpr char kIppScheme[] = "ipp"; constexpr char kIppsScheme[] = "ipps"; @@ -60,6 +63,15 @@ constexpr int kIppsPort = 443; // enums must never be renumbered or deleted and reused. enum PpdSourceForHistogram { kUser = 0, kScs = 1, kPpdSourceMax }; +// A parsed representation of a printer uri. +struct PrinterUri { + bool encrypted = false; + std::string scheme; + std::string host; + int port = url::SpecialPort::PORT_INVALID; + std::string path; +}; + void RecordPpdSource(const PpdSourceForHistogram& source) { UMA_HISTOGRAM_ENUMERATION("Printing.CUPS.PpdSource", source, kPpdSourceMax); } @@ -69,6 +81,76 @@ void OnRemovedPrinter(const Printer::PrinterProtocol& protocol, bool success) { Printer::PrinterProtocol::kProtocolMax); } +// Log if the IPP attributes request was succesful. +void RecordIppQuerySuccess(bool success) { + UMA_HISTOGRAM_BOOLEAN("Printing.CUPS.IppAttributesSuccess", success); +} + +// Parsees |printer_uri| into its components and written into |uri|. Returns +// true if the uri was parsed successfully, returns false otherwise. No changes +// are made to |uri| if this function returns false. +bool ParseUri(const std::string& printer_uri, PrinterUri* uri) { + DCHECK(uri); + const char* uri_ptr = printer_uri.c_str(); + url::Parsed parsed; + url::ParseStandardURL(uri_ptr, printer_uri.length(), &parsed); + if (!parsed.scheme.is_valid() || !parsed.host.is_valid() || + !parsed.path.is_valid()) { + return false; + } + base::StringPiece scheme(&uri_ptr[parsed.scheme.begin], parsed.scheme.len); + base::StringPiece host(&uri_ptr[parsed.host.begin], parsed.host.len); + base::StringPiece path(&uri_ptr[parsed.path.begin], parsed.path.len); + + bool encrypted = scheme != kIppScheme; + int port = ParsePort(uri_ptr, parsed.port); + // Port not specified. + if (port == url::SpecialPort::PORT_UNSPECIFIED || + port == url::SpecialPort::PORT_INVALID) { + if (scheme == kIppScheme) { + port = kIppPort; + } else if (scheme == kIppsScheme) { + port = kIppsPort; + } + } + + uri->encrypted = encrypted; + uri->scheme = scheme.as_string(); + uri->host = host.as_string(); + uri->port = port; + uri->path = path.as_string(); + + return true; +} + +// Returns true if |printer_uri| is an IPP uri. +bool IsIppUri(base::StringPiece printer_uri) { + base::StringPiece::size_type separator_location = + printer_uri.find(url::kStandardSchemeSeparator); + if (separator_location == base::StringPiece::npos) { + return false; + } + + base::StringPiece scheme_part = printer_uri.substr(0, separator_location); + return scheme_part == kIppScheme || scheme_part == kIppsScheme; +} + +// Query an IPP printer to check for autoconf support where the printer is +// located at |printer_uri|. Results are reported through |callback|. It is an +// error to attempt this with a non-IPP printer. +void QueryAutoconf(const std::string& printer_uri, + const PrinterInfoCallback& callback) { + PrinterUri uri; + // Behavior for querying a non-IPP uri is undefined and disallowed. + if (!IsIppUri(printer_uri) || !ParseUri(printer_uri, &uri)) { + LOG(WARNING) << "Printer uri is invalid: " << printer_uri; + callback.Run(false, "", "", "", false); + return; + } + + QueryIppPrinter(uri.host, uri.port, uri.path, uri.encrypted, callback); +} + // Create an empty CupsPrinterInfo dictionary value. It should be consistent // with the fields in js side. See cups_printers_browser_proxy.js for the // definition of CupsPrinterInfo. @@ -92,6 +174,16 @@ std::unique_ptr<base::DictionaryValue> CreateEmptyPrinterInfo() { return printer_info; } +// Formats a host and port string. The |port| portion is omitted if +// it is unspecified or invalid. +std::string PrinterAddress(const std::string& host, int port) { + if (port != url::PORT_UNSPECIFIED && port != url::PORT_INVALID) { + return base::StringPrintf("%s:%d", host.c_str(), port); + } + + return host; +} + // Returns a JSON representation of |printer| as a CupsPrinterInfo. std::unique_ptr<base::DictionaryValue> GetPrinterInfo(const Printer& printer) { std::unique_ptr<base::DictionaryValue> printer_info = @@ -102,34 +194,27 @@ std::unique_ptr<base::DictionaryValue> GetPrinterInfo(const Printer& printer) { printer_info->SetString("printerManufacturer", printer.manufacturer()); printer_info->SetString("printerModel", printer.model()); printer_info->SetString("printerMakeAndModel", printer.make_and_model()); - // Get protocol, ip address and queue from the printer's URI. - const std::string printer_uri = printer.uri(); - url::Parsed parsed; - url::ParseStandardURL(printer_uri.c_str(), printer_uri.length(), &parsed); - std::string scheme; - std::string host; - std::string path; - if (parsed.scheme.len > 0) - scheme = std::string(printer_uri, parsed.scheme.begin, parsed.scheme.len); - if (parsed.host.len > 0) - host = std::string(printer_uri, parsed.host.begin, parsed.host.len); - if (parsed.path.len > 0) - path = std::string(printer_uri, parsed.path.begin, parsed.path.len); - if (base::ToLowerASCII(scheme) == "usb") { + PrinterUri uri; + if (!ParseUri(printer.uri(), &uri)) { + return nullptr; + } + + if (base::ToLowerASCII(uri.scheme) == "usb") { // USB has URI path (and, maybe, query) components that aren't really // associated with a queue -- the mapping between printing semantics and URI // semantics breaks down a bit here. From the user's point of view, the // entire host/path/query block is the printer address for USB. printer_info->SetString("printerAddress", - printer_uri.substr(parsed.host.begin)); + printer.uri().substr(kUsbSchemeLength)); } else { - printer_info->SetString("printerAddress", host); - if (!path.empty()) { - printer_info->SetString("printerQueue", path.substr(1)); + printer_info->SetString("printerAddress", + PrinterAddress(uri.host, uri.port)); + if (!uri.path.empty()) { + printer_info->SetString("printerQueue", uri.path.substr(1)); } } - printer_info->SetString("printerProtocol", base::ToLowerASCII(scheme)); + printer_info->SetString("printerProtocol", base::ToLowerASCII(uri.scheme)); return printer_info; } @@ -294,7 +379,7 @@ void CupsPrintersHandler::HandleGetPrinterInfo(const base::ListValue* args) { if (printer_address.empty()) { // Run the failure callback. - OnPrinterInfo(callback_id, false, "", "", "", false); + OnAutoconfQueried(callback_id, false, "", "", "", false); return; } @@ -306,43 +391,62 @@ void CupsPrintersHandler::HandleGetPrinterInfo(const base::ListValue* args) { return; } - // Parse url to separate address and port. ParseStandardURL expects a scheme, - // so add the printer_protocol. + DCHECK(printer_protocol == kIppScheme || printer_protocol == kIppsScheme) + << "Printer info requests only supported for IPP and IPPS printers"; std::string printer_uri = - printer_protocol + url::kStandardSchemeSeparator + printer_address; - const char* uri_ptr = printer_uri.c_str(); - url::Parsed parsed; - url::ParseStandardURL(uri_ptr, printer_uri.length(), &parsed); - base::StringPiece host(&printer_uri[parsed.host.begin], parsed.host.len); + base::StringPrintf("%s://%s/%s", printer_protocol.c_str(), + printer_address.c_str(), printer_queue.c_str()); + QueryAutoconf(printer_uri, + base::Bind(&CupsPrintersHandler::OnAutoconfQueried, + weak_factory_.GetWeakPtr(), callback_id)); +} - bool encrypted = printer_protocol != kIppScheme; - int port = ParsePort(uri_ptr, parsed.port); - // Port not specified. - if (port == url::SpecialPort::PORT_UNSPECIFIED || - port == url::SpecialPort::PORT_INVALID) { - if (printer_protocol == kIppScheme) { - port = kIppPort; - } else if (printer_protocol == kIppsScheme) { - port = kIppsPort; - } else { - // Port was not defined explicitly and scheme is not recognized. Cannot - // infer a port number. - NOTREACHED() << "Unrecognized protocol. Port was not set."; +void CupsPrintersHandler::OnAutoconfQueriedDiscovered( + std::unique_ptr<Printer> printer, + bool success, + const std::string& make, + const std::string& model, + const std::string& make_and_model, + bool ipp_everywhere) { + RecordIppQuerySuccess(success); + + if (success) { + // If we queried a valid make and model, use it. The mDNS record isn't + // guaranteed to have it. However, don't overwrite it if the printer + // advertises an empty value through printer-make-and-model. + if (!make_and_model.empty()) { + // manufacturer and model are set with make_and_model because they are + // derived from make_and_model for compatability and are slated for + // removal. + printer->set_manufacturer(make); + printer->set_model(model); + printer->set_make_and_model(make_and_model); + } + + // Autoconfig available, use it. + if (ipp_everywhere) { + printer->mutable_ppd_reference()->autoconf = true; + printer_configurer_->SetUpPrinter( + *printer, base::Bind(&CupsPrintersHandler::OnAddedDiscoveredPrinter, + weak_factory_.GetWeakPtr(), *printer)); + return; } } - QueryIppPrinter(host.as_string(), port, printer_queue, encrypted, - base::Bind(&CupsPrintersHandler::OnPrinterInfo, - weak_factory_.GetWeakPtr(), callback_id)); + // We don't have enough from discovery to configure the printer. Fill in as + // much information as we can about the printer, and ask the user to supply + // the rest. + FireWebUIListener("on-manually-add-discovered-printer", + *GetPrinterInfo(*printer)); } -void CupsPrintersHandler::OnPrinterInfo(const std::string& callback_id, - bool success, - const std::string& make, - const std::string& model, - const std::string& make_and_model, - bool ipp_everywhere) { - UMA_HISTOGRAM_BOOLEAN("Printing.CUPS.IppAttributesSuccess", success); +void CupsPrintersHandler::OnAutoconfQueried(const std::string& callback_id, + bool success, + const std::string& make, + const std::string& model, + const std::string& make_and_model, + bool ipp_everywhere) { + RecordIppQuerySuccess(success); if (!success) { base::DictionaryValue reject; @@ -684,24 +788,36 @@ void CupsPrintersHandler::HandleAddDiscoveredPrinter( std::string printer_id; CHECK(args->GetString(0, &printer_id)); - auto printer = printers_manager_->GetPrinter(printer_id); + std::unique_ptr<Printer> printer = printers_manager_->GetPrinter(printer_id); if (printer == nullptr) { // Printer disappeared, so we don't have information about it anymore and // can't really do much. Fail the add. FireWebUIListener("on-add-cups-printer", base::Value(false), base::Value(printer_id)); - } else if (printer->ppd_reference().autoconf || - !printer->ppd_reference().effective_make_and_model.empty() || - !printer->ppd_reference().user_supplied_ppd_url.empty()) { + return; + } + + if (printer->ppd_reference().autoconf || + !printer->ppd_reference().effective_make_and_model.empty() || + !printer->ppd_reference().user_supplied_ppd_url.empty()) { // If we have something that looks like a ppd reference for this printer, // try to configure it. printer_configurer_->SetUpPrinter( *printer, base::Bind(&CupsPrintersHandler::OnAddedDiscoveredPrinter, weak_factory_.GetWeakPtr(), *printer)); + return; + } + + // The mDNS record doesn't guarantee we can setup the printer. Query it to + // see if we want to try IPP. + const std::string printer_uri = printer->effective_uri(); + if (IsIppUri(printer_uri)) { + QueryAutoconf( + printer_uri, + base::Bind(&CupsPrintersHandler::OnAutoconfQueriedDiscovered, + weak_factory_.GetWeakPtr(), base::Passed(&printer))); } else { - // We don't have enough from discovery to configure the printer. Fill in as - // much information as we can about the printer, and ask the user to supply - // the rest. + // If it's not an IPP printer, the user must choose a PPD. FireWebUIListener("on-manually-add-discovered-printer", *GetPrinterInfo(*printer)); } diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h index 8a92dd25f51..f1106406c3a 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h @@ -62,12 +62,20 @@ class CupsPrintersHandler : public ::settings::SettingsPageUIHandler, // string. |ipp_everywhere| indicates if configuration using the CUPS IPP // Everywhere driver should be attempted. If |success| is false, the values of // |make|, |model|, |make_and_model|, and |ipp_everywhere| are not specified. - void OnPrinterInfo(const std::string& callback_id, - bool success, - const std::string& make, - const std::string& model, - const std::string& make_and_model, - bool ipp_everywhere); + void OnAutoconfQueried(const std::string& callback_id, + bool success, + const std::string& make, + const std::string& model, + const std::string& make_and_model, + bool ipp_everywhere); + + // Handles the callback for HandleGetPrinterInfo for a discovered printer. + void OnAutoconfQueriedDiscovered(std::unique_ptr<Printer> printer, + bool success, + const std::string& make, + const std::string& model, + const std::string& make_and_model, + bool ipp_everywhere); void HandleAddCupsPrinter(const base::ListValue* args); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.cc index 0d356464b37..ea381abb6c4 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.cc @@ -28,15 +28,9 @@ constexpr char kAppLockScreenSupportKey[] = "lockScreenSupport"; } // namespace -StylusHandler::StylusHandler() { - NoteTakingHelper::Get()->AddObserver(this); - ui::InputDeviceManager::GetInstance()->AddObserver(this); -} +StylusHandler::StylusHandler() : note_observer_(this), input_observer_(this) {} -StylusHandler::~StylusHandler() { - ui::InputDeviceManager::GetInstance()->RemoveObserver(this); - NoteTakingHelper::Get()->RemoveObserver(this); -} +StylusHandler::~StylusHandler() = default; void StylusHandler::RegisterMessages() { DCHECK(web_ui()); @@ -60,6 +54,16 @@ void StylusHandler::RegisterMessages() { base::Bind(&StylusHandler::ShowPlayStoreApps, base::Unretained(this))); } +void StylusHandler::OnJavascriptAllowed() { + note_observer_.Add(NoteTakingHelper::Get()); + input_observer_.Add(ui::InputDeviceManager::GetInstance()); +} + +void StylusHandler::OnJavascriptDisallowed() { + note_observer_.RemoveAll(); + input_observer_.RemoveAll(); +} + void StylusHandler::OnAvailableNoteTakingAppsUpdated() { UpdateNoteTakingApps(); } @@ -99,12 +103,12 @@ void StylusHandler::UpdateNoteTakingApps() { } } - AllowJavascript(); FireWebUIListener("onNoteTakingAppsUpdated", apps_list, base::Value(waiting_for_android)); } void StylusHandler::RequestApps(const base::ListValue* unused_args) { + AllowJavascript(); UpdateNoteTakingApps(); } @@ -133,13 +137,13 @@ void StylusHandler::SetPreferredNoteTakingAppEnabledOnLockScreen( } void StylusHandler::HandleInitialize(const base::ListValue* args) { + AllowJavascript(); if (ui::InputDeviceManager::GetInstance()->AreDeviceListsComplete()) SendHasStylus(); } void StylusHandler::SendHasStylus() { DCHECK(ui::InputDeviceManager::GetInstance()->AreDeviceListsComplete()); - AllowJavascript(); FireWebUIListener("has-stylus-changed", base::Value(ash::palette_utils::HasStylusInput())); } diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.h index ac52790f5ad..8f2800d4d86 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.h @@ -9,6 +9,7 @@ #include <string> #include "base/macros.h" +#include "base/scoped_observer.h" #include "chrome/browser/chromeos/note_taking_helper.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" #include "ui/events/devices/input_device_event_observer.h" @@ -17,12 +18,16 @@ namespace base { class ListValue; } +namespace ui { +class InputDeviceManager; +} + namespace chromeos { namespace settings { // Chrome OS stylus settings handler. class StylusHandler : public ::settings::SettingsPageUIHandler, - public chromeos::NoteTakingHelper::Observer, + public NoteTakingHelper::Observer, public ui::InputDeviceEventObserver { public: StylusHandler(); @@ -30,8 +35,8 @@ class StylusHandler : public ::settings::SettingsPageUIHandler, // SettingsPageUIHandler implementation. void RegisterMessages() override; - void OnJavascriptAllowed() override {} - void OnJavascriptDisallowed() override {} + void OnJavascriptAllowed() override; + void OnJavascriptDisallowed() override; // chromeos::NoteTakingHelper::Observer implementation. void OnAvailableNoteTakingAppsUpdated() override; @@ -58,6 +63,11 @@ class StylusHandler : public ::settings::SettingsPageUIHandler, // IDs of available note-taking apps. std::set<std::string> note_taking_app_ids_; + // Observer registration. + ScopedObserver<NoteTakingHelper, NoteTakingHelper::Observer> note_observer_; + ScopedObserver<ui::InputDeviceManager, ui::InputDeviceEventObserver> + input_observer_; + DISALLOW_COPY_AND_ASSIGN(StylusHandler); }; diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc index d046f21e27d..69b4aef7ff2 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc @@ -48,7 +48,7 @@ void GoogleAssistantHandler::HandleSetGoogleAssistantEnabled( auto* service = arc::ArcVoiceInteractionFrameworkService::GetForBrowserContext(profile_); if (service) - service->SetVoiceInteractionEnabled(enabled); + service->SetVoiceInteractionEnabled(enabled, base::BindOnce([](bool) {})); } void GoogleAssistantHandler::HandleSetGoogleAssistantContextEnabled( |