summaryrefslogtreecommitdiff
path: root/chromium/components/printing/browser/printer_capabilities.cc
blob: e1c3f4de0abed464f70242e84abc229697e630c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
// 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.

#include "components/printing/browser/printer_capabilities.h"

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/values.h"
#include "build/build_config.h"
#include "build/buildflag.h"
#include "components/crash/core/common/crash_keys.h"
#include "components/printing/browser/printing_buildflags.h"
#include "components/printing/common/cloud_print_cdd_conversion.h"
#include "printing/backend/print_backend.h"
#include "printing/backend/print_backend_consts.h"

#if defined(OS_WIN)
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"
#endif  // defined(OS_WIN)

#if defined(OS_CHROMEOS)
#include "base/feature_list.h"
#include "components/printing/browser/ipp_l10n.h"
#include "components/strings/grit/components_strings.h"
#include "printing/printing_features.h"
#include "ui/base/l10n/l10n_util.h"
#endif  // defined(OS_CHROMEOS)

#if BUILDFLAG(PRINT_MEDIA_L10N_ENABLED)
#include "components/printing/browser/print_media_l10n.h"
#if defined(OS_APPLE)
#include "printing/printing_features.h"
#endif  // defined(OS_APPLE)
#endif  // BUILDFLAG(PRINT_MEDIA_L10N_ENABLED)

namespace printing {

const char kPrinter[] = "printer";

namespace {

#if BUILDFLAG(PRINT_MEDIA_L10N_ENABLED)
// Iterate on the Papers of a given printer |info| and set the
// display_name members, localizing where possible. We expect the
// backend to have populated non-empty display names already, so we
// don't touch media display names that we can't localize.
void PopulateAllPaperDisplayNames(PrinterSemanticCapsAndDefaults* info) {
  std::string default_paper_display =
      LocalizePaperDisplayName(info->default_paper.vendor_id);
  if (!default_paper_display.empty()) {
    info->default_paper.display_name = default_paper_display;
  }

  for (PrinterSemanticCapsAndDefaults::Paper& paper : info->papers) {
    std::string display = LocalizePaperDisplayName(paper.vendor_id);
    if (!display.empty()) {
      paper.display_name = display;
    }
  }
}
#endif  // BUILDFLAG(PRINT_MEDIA_L10N_ENABLED)

#if defined(OS_CHROMEOS)
void PopulateAdvancedCapsLocalization(
    std::vector<AdvancedCapability>* advanced_capabilities) {
  auto& l10n_map = CapabilityLocalizationMap();
  for (AdvancedCapability& capability : *advanced_capabilities) {
    auto it = l10n_map.find(capability.name);
    if (it != l10n_map.end())
      capability.display_name = l10n_util::GetStringUTF8(it->second);

    for (AdvancedCapabilityValue& value : capability.values) {
      auto it = l10n_map.find(capability.name + "/" + value.name);
      if (it != l10n_map.end())
        value.display_name = l10n_util::GetStringUTF8(it->second);
    }
  }
}
#endif  // defined(OS_CHROMEOS)

#ifndef TOOLKIT_QT
// Returns a dictionary representing printer capabilities as CDD.  Returns
// an empty dictionary if a dictionary could not be generated.
base::Value GetPrinterCapabilitiesOnBlockingTaskRunner(
    const std::string& device_name,
    PrinterSemanticCapsAndDefaults::Papers user_defined_papers,
    bool has_secure_protocol,
    scoped_refptr<PrintBackend> backend) {
  DCHECK(!device_name.empty());

  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);

  VLOG(1) << "Get printer capabilities start for " << device_name;
  crash_keys::ScopedPrinterInfo crash_key(
      backend->GetPrinterDriverInfo(device_name));

  PrinterSemanticCapsAndDefaults info;
  if (!backend->GetPrinterSemanticCapsAndDefaults(device_name, &info)) {
    LOG(WARNING) << "Failed to get capabilities for " << device_name;
    return base::Value(base::Value::Type::DICTIONARY);
  }

#if BUILDFLAG(PRINT_MEDIA_L10N_ENABLED)
  bool populate_paper_display_names = true;
#if defined(OS_APPLE)
  // Paper display name localization requires standardized vendor ID names
  // populated by CUPS IPP. If the CUPS IPP backend is not enabled, localization
  // will not properly occur.
  populate_paper_display_names =
      base::FeatureList::IsEnabled(features::kCupsIppPrintingBackend);
#endif
  if (populate_paper_display_names)
    PopulateAllPaperDisplayNames(&info);
#endif  // BUILDFLAG(PRINT_MEDIA_L10N_ENABLED)

  info.user_defined_papers = std::move(user_defined_papers);

#if defined(OS_CHROMEOS)
  if (!has_secure_protocol)
    info.pin_supported = false;

  if (base::FeatureList::IsEnabled(printing::features::kAdvancedPpdAttributes))
    PopulateAdvancedCapsLocalization(&info.advanced_capabilities);
#endif  // defined(OS_CHROMEOS)

  return cloud_print::PrinterSemanticCapsAndDefaultsToCdd(info);
}
#endif

}  // namespace

#if defined(OS_WIN)
std::string GetUserFriendlyName(const std::string& printer_name) {
  // |printer_name| may be a UNC path like \\printserver\printername.
  if (!base::StartsWith(printer_name, "\\\\",
                        base::CompareCase::INSENSITIVE_ASCII)) {
    return printer_name;
  }

  // If it is a UNC path, split the "printserver\printername" portion and
  // generate a friendly name, like Windows does.
  std::string printer_name_trimmed = printer_name.substr(2);
  std::vector<std::string> tokens = base::SplitString(
      printer_name_trimmed, "\\", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
  if (tokens.size() != 2 || tokens[0].empty() || tokens[1].empty())
    return printer_name;
  return l10n_util::GetStringFUTF8(
      IDS_PRINT_PREVIEW_FRIENDLY_WIN_NETWORK_PRINTER_NAME,
      base::UTF8ToUTF16(tokens[1]), base::UTF8ToUTF16(tokens[0]));
}
#endif

#ifndef TOOLKIT_QT
base::Value GetSettingsOnBlockingTaskRunner(
    const std::string& device_name,
    const PrinterBasicInfo& basic_info,
    PrinterSemanticCapsAndDefaults::Papers user_defined_papers,
    bool has_secure_protocol,
    scoped_refptr<PrintBackend> print_backend) {
  SCOPED_UMA_HISTOGRAM_TIMER("Printing.PrinterCapabilities");
  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);

  base::Value printer_info(base::Value::Type::DICTIONARY);
  printer_info.SetKey(kSettingDeviceName, base::Value(device_name));
  printer_info.SetKey(kSettingPrinterName,
                      base::Value(basic_info.display_name));
  printer_info.SetKey(kSettingPrinterDescription,
                      base::Value(basic_info.printer_description));

  base::Value options(base::Value::Type::DICTIONARY);

#if defined(OS_CHROMEOS)
  printer_info.SetKey(
      kCUPSEnterprisePrinter,
      base::Value(base::Contains(basic_info.options, kCUPSEnterprisePrinter) &&
                  basic_info.options.at(kCUPSEnterprisePrinter) == kValueTrue));
#endif  // defined(OS_CHROMEOS)

  printer_info.SetKey(kSettingPrinterOptions, std::move(options));

  base::Value printer_info_capabilities(base::Value::Type::DICTIONARY);
  printer_info_capabilities.SetKey(kPrinter, std::move(printer_info));
  printer_info_capabilities.SetKey(
      kSettingCapabilities, GetPrinterCapabilitiesOnBlockingTaskRunner(
                                device_name, std::move(user_defined_papers),
                                has_secure_protocol, print_backend));
  return printer_info_capabilities;
}
#endif
}  // namespace printing